Fix for java to allow password, european dates,from Peter T Mount

This commit is contained in:
Bruce Momjian 1997-10-30 18:24:44 +00:00
parent 2cc73c0d42
commit 0e58306857
4 changed files with 237 additions and 76 deletions

View File

@ -4,58 +4,104 @@ import java.sql.*;
class JDBC_Test class JDBC_Test
{ {
public JDBC_Test() public JDBC_Test()
{
}
public static void main(String argv[])
{
String url = new String(argv[0]);
String usr = new String(argv[1]);
String pwd = new String(argv[2]);
Connection db;
Statement s;
ResultSet rs;
// This line outputs debug information to stderr. To enable this, simply
// remove the //
DriverManager.setLogStream(System.err);
// Load the driver
try {
Class.forName("postgresql.Driver");
} catch (ClassNotFoundException e) {
System.err.println("Exception: " + e.toString());
}
// Lets do a few things -- it doesn't do everything, but
// it tests out basic functionality
try {
System.out.println("Connecting to Database URL = " + url);
db = DriverManager.getConnection(url, usr, pwd);
System.out.println("Connected...Now creating a statement");
s = db.createStatement();
// test Date & Warnings
System.out.println("Ok... now set European date style");
s.executeUpdate("set datestyle='european'");
System.out.println("and see what style we are now using (handled by warnings)");
s.executeUpdate("show datestyle");
SQLWarning sw = db.getWarnings();
while(sw!=null) {
System.out.println("--> "+sw.getMessage());
sw=sw.getNextWarning();
}
db.clearWarnings();
System.out.println("Ok...now we will create a table");
s.executeUpdate("create table test (a int2, b int2,c timestamp,d date)");
System.out.println("Now we will insert some columns");
s.executeUpdate("insert into test values (1, 1,'now','now')");
s.executeUpdate("insert into test values (2, 1,'now','01-11-1997')"); // As we are in european, this should mean 1 November 1997
s.executeUpdate("insert into test values (3, 1,'now','11-01-1997')"); // As we are in european, this should mean 11 January 1997
System.out.println("Inserted some data");
System.out.println("Now lets try a select");
rs = s.executeQuery("select a, b,c,d from test");
System.out.println("Back from the select...the following are results");
System.out.println("row a b c d 'd as string'");
int i = 0;
while (rs.next())
{ {
int a = rs.getInt("a"); // Example of retriving by column name
int b = rs.getInt("b");
Timestamp c = rs.getTimestamp(3); // Example of by column number
java.sql.Date d = rs.getDate(4); // Note, java.sql.Date here
System.out.println("row " + i + " " + a + " " + b + " " + c + " " + d + " '"+rs.getString(4)+"'");
i++;
} }
public static void main(String argv[]) // This is a bug at the moment... when you use set datestyle
// it must be followed by show datestyle
System.out.println("Now switch to US date format");
s.executeUpdate("set datestyle='US'");
s.executeUpdate("show datestyle");
System.out.println("Now lets try a select");
rs = s.executeQuery("select a, b,c,d from test");
System.out.println("Back from the select...the following are results");
//int i = 0;
System.out.println("row a b c d 'd as string'");
while (rs.next())
{ {
String url = new String(argv[0]); int a = rs.getInt("a"); // Example of retriving by column name
Connection db; int b = rs.getInt("b");
Statement s; Timestamp c = rs.getTimestamp(3); // Example of by column number
ResultSet rs; java.sql.Date d = rs.getDate(4); // Note, java.sql.Date here
System.out.println("row " + i + " " + a + " " + b + " " + c + " " + d + " '"+rs.getString(4)+"'");
// Load the driver i++;
try
{
Class.forName("postgresql.Driver");
} catch (ClassNotFoundException e) {
System.err.println("Exception: " + e.toString());
}
// Lets do a few things -- it doesn't do everything, but
// it tests out basic functionality
try
{
System.out.println("Connecting to Database URL = " + url);
db = DriverManager.getConnection(url, "adrian", "");
System.out.println("Connected...Now creating a statement");
s = db.createStatement();
System.out.println("Ok...now we will create a table");
s.executeUpdate("create table test (a int2, b int2)");
System.out.println("Now we will insert some columns");
s.executeUpdate("insert into test values (1, 1)");
s.executeUpdate("insert into test values (2, 1)");
s.executeUpdate("insert into test values (3, 1)");
System.out.println("Inserted some data");
System.out.println("Now lets try a select");
rs = s.executeQuery("select a, b from test");
System.out.println("Back from the select...the following are results");
int i = 0;
while (rs.next())
{
int a = rs.getInt("a");
int b = rs.getInt("b");
System.out.println("row " + i + " " + a + " " + b);
i++;
}
System.out.println("Ok...dropping the table");
s.executeUpdate("drop table test");
System.out.println("Now closing the connection");
s.close();
db.close();
} catch (SQLException e) {
System.out.println("Exception: " + e.toString());
}
} }
System.out.println("Ok...dropping the table");
s.executeUpdate("drop table test");
System.out.println("Now closing the connection");
s.close();
db.close();
} catch (SQLException e) {
System.out.println("Exception: " + e.toString());
}
}
} }

View File

@ -112,6 +112,17 @@ them to the URL. eg:
jdbc:postgresql:database?user=me jdbc:postgresql:database?user=me
jdbc:postgresql:database?user=me&password=mypass jdbc:postgresql:database?user=me&password=mypass
By default, the driver doesn't use password authentication. You can enable
this by adding the argument auth. ie:
jdbc:postgresql:database?user=me&password=mypass&auth=y
or if passing the user & password directly via DriverManager.getConnection():
jdbc:postgresql:database?auth=y
PS: 'y' could be anything, aslong as there is something after the '='
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
That's the basics related to this driver. You'll need to read the JDBC Docs That's the basics related to this driver. You'll need to read the JDBC Docs
@ -120,6 +131,34 @@ on how to use it.
POSTGRESQL SPECIFICS POSTGRESQL SPECIFICS
-------------------- --------------------
Date datatype:
The driver now supports US and European date styles (although it is currently
limited to postgres format).
Basically the US like to format their dates as mm-dd-yyyy, while in Europe,
we like to use dd-mm-yyyy. Postgres supports this by the DateStyle variable.
From psql, you can issue "set datestyle='european';" to set european style,
and "set datestyle='us';" to set the US format. You can see what the current
value for this with "show datestyle;".
The driver now issues the "show datestyle;" query when it first connects, so
any call to ResultSet.getDate() how returns the correct date.
One caveat though: if you change the datestyle from within JDBC, you must also
issue the "show datestyle" query. Without this, the driver will not know of
the change.
ie:
Statement s = db.createStatement();
...
s.executeUpdate("set datestyle='european'");
s.executeUpdate("show datestyle");
..
s.close();
------------------
JDBC supports database specific data types using the getObject() call. The JDBC supports database specific data types using the getObject() call. The
following types have their own Java equivalents supplied by the driver: following types have their own Java equivalents supplied by the driver:
@ -140,9 +179,10 @@ syntax for writing these to the database.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Peter T Mount, August 30 1997 Peter T Mount, October 28 1997
home email: pmount@maidast.demon.co.uk http://www.demon.co.uk/finder home email: pmount@maidast.demon.co.uk http://www.demon.co.uk/finder
work email: peter@maidstone.gov.uk http://www.maidstone.gov.uk work email: peter@maidstone.gov.uk http://www.maidstone.gov.uk
Adrian Hall Adrian Hall
email: adrian@hottub.org email: adrian@hottub.org

View File

@ -36,11 +36,15 @@ public class Connection implements java.sql.Connection
private String PG_PASSWORD; private String PG_PASSWORD;
private String PG_DATABASE; private String PG_DATABASE;
private boolean PG_STATUS; private boolean PG_STATUS;
private boolean PG_AUTH; // true, then password auth used
public boolean CONNECTION_OK = true; public boolean CONNECTION_OK = true;
public boolean CONNECTION_BAD = false; public boolean CONNECTION_BAD = false;
private int STARTUP_CODE = 7; private int STARTUP_CODE = STARTUP_USER;
private static final int STARTUP_USER = 7; // User auth
private static final int STARTUP_PASS = 14; // Password auth
private static final int STARTUP_LEN = 288; // Length of a startup packet
private boolean autoCommit = true; private boolean autoCommit = true;
private boolean readOnly = false; private boolean readOnly = false;
@ -49,6 +53,12 @@ public class Connection implements java.sql.Connection
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
// This is false for US, true for European date formats
protected boolean europeanDates = false;
// Now handle notices as warnings, so things like "show" now work
protected SQLWarning firstWarning = null;
/** /**
* Connect to a PostgreSQL database back end. * Connect to a PostgreSQL database back end.
* *
@ -63,7 +73,7 @@ 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 = 288; // Length of a startup packet int len = STARTUP_LEN; // Length of a startup packet
this_driver = d; this_driver = d;
this_url = new String(url); this_url = new String(url);
@ -74,6 +84,13 @@ 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;
if(info.getProperty("auth") != null) {
PG_AUTH=true;
STARTUP_CODE=STARTUP_PASS;
} else {
STARTUP_CODE=STARTUP_USER;
}
try try
{ {
pg_stream = new PG_Stream(host, port); pg_stream = new PG_Stream(host, port);
@ -88,10 +105,34 @@ public class Connection implements java.sql.Connection
pg_stream.SendInteger(STARTUP_CODE, 4); len -= 4; pg_stream.SendInteger(STARTUP_CODE, 4); len -= 4;
pg_stream.Send(database.getBytes(), 64); len -= 64; pg_stream.Send(database.getBytes(), 64); len -= 64;
pg_stream.Send(PG_USER.getBytes(), len); pg_stream.Send(PG_USER.getBytes(), len);
// Send the password packet if required
if(PG_AUTH) {
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);
}
} catch (IOException e) { } catch (IOException e) {
throw new SQLException("Connection failed: " + e.toString()); throw new SQLException("Connection failed: " + e.toString());
} }
ExecSQL(" "); // Test connection
// Find out the date style by issuing the SQL: show datestyle
// This actually issues a warning, and our own warning handling
// code handles this itself.
//
// Also, this query replaced the NULL query issued to test the
// connection.
//
clearWarnings();
ExecSQL("show datestyle");
// Mark the connection as ok, and cleanup
clearWarnings();
PG_STATUS = CONNECTION_OK; PG_STATUS = CONNECTION_OK;
} }
@ -391,7 +432,7 @@ public class Connection implements java.sql.Connection
*/ */
public SQLWarning getWarnings() throws SQLException public SQLWarning getWarnings() throws SQLException
{ {
return null; // We handle warnings as errors return firstWarning;
} }
/** /**
@ -402,13 +443,36 @@ public class Connection implements java.sql.Connection
*/ */
public void clearWarnings() throws SQLException public void clearWarnings() throws SQLException
{ {
// Not handles since we handle wanrings as errors firstWarning = null;
} }
// ********************************************************** // **********************************************************
// END OF PUBLIC INTERFACE // END OF PUBLIC INTERFACE
// ********************************************************** // **********************************************************
/**
* This adds a warning to the warning chain
*/
public void addWarning(String msg)
{
// Add the warning to the chain
if(firstWarning!=null)
firstWarning.setNextWarning(new SQLWarning(msg));
else
firstWarning = new SQLWarning(msg);
// Now check for some specific messages
// This is generated by the SQL "show datestyle"
if(msg.startsWith("NOTICE:DateStyle")) {
if(msg.indexOf("with US")==-1)
europeanDates=true;
else
europeanDates=false;
System.err.println("europeanDates="+europeanDates);
}
}
/** /**
* Send a query to the backend. Returns one of the ResultSet * Send a query to the backend. Returns one of the ResultSet
* objects. * objects.
@ -497,7 +561,8 @@ public class Connection implements java.sql.Connection
case 'N': // Error Notification case 'N': // Error Notification
msg = pg_stream.ReceiveString(4096); msg = pg_stream.ReceiveString(4096);
PrintStream log = DriverManager.getLogStream(); PrintStream log = DriverManager.getLogStream();
log.println(msg); if(log!=null) log.println(msg);
addWarning(msg);
break; break;
case 'P': // Portal Name case 'P': // Portal Name
String pname = pg_stream.ReceiveString(8192); String pname = pg_stream.ReceiveString(8192);

View File

@ -377,17 +377,22 @@ public class ResultSet implements java.sql.ResultSet
if (s != null) if (s != null)
{ {
try try {
{ if (s.length() != 10)
if (s.length() != 10) throw new NumberFormatException("Wrong Length!");
throw new NumberFormatException("Wrong Length!"); int mon = Integer.parseInt(s.substring(0,2));
int mon = Integer.parseInt(s.substring(0,2)); int day = Integer.parseInt(s.substring(3,5));
int day = Integer.parseInt(s.substring(3,5)); int yr = Integer.parseInt(s.substring(6));
int yr = Integer.parseInt(s.substring(6)); if(connection.europeanDates) {
return new java.sql.Date(yr - 1900, mon -1, day); // We europeans prefer dd mm yyyy
} catch (NumberFormatException e) { int t = mon;
throw new SQLException("Bad Date Form: " + s); mon = day;
day = t;
} }
return new java.sql.Date(yr - 1900, mon -1, day);
} catch (NumberFormatException e) {
throw new SQLException("Bad Date Form: " + s);
}
} }
return null; // SQL NULL return null; // SQL NULL
} }
@ -432,19 +437,24 @@ public class ResultSet implements java.sql.ResultSet
public Timestamp getTimestamp(int columnIndex) throws SQLException public Timestamp getTimestamp(int columnIndex) throws SQLException
{ {
String s = getString(columnIndex); String s = getString(columnIndex);
DateFormat df = DateFormat.getDateInstance(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzz");
if (s != null) if (s != null)
{ {
try int TZ = new Float(s.substring(19)).intValue();
{ TZ = TZ * 60 * 60 * 1000;
java.sql.Date d = (java.sql.Date)df.parse(s); TimeZone zone = TimeZone.getDefault();
return new Timestamp(d.getTime()); zone.setRawOffset(TZ);
} catch (ParseException e) { String nm = zone.getID();
throw new SQLException("Bad Timestamp Format: " + s); s = s.substring(0,18) + nm;
} try {
java.util.Date d = df.parse(s);
return new Timestamp(d.getTime());
} catch (ParseException e) {
throw new SQLException("Bad Timestamp Format: at " + e.getErrorOffset() + " in " + s);
}
} }
return null; // SQL NULL return null; // SQL NULL
} }
/** /**