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]);
- Connection db;
- Statement s;
- ResultSet rs;
-
- // 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, "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());
- }
+ 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++;
}
+
+ 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());
+ }
+ }
}
jdbc:postgresql:database?user=me
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
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
following types have their own Java equivalents supplied by the driver:
---------------------------------------------------------------------------
-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
work email: peter@maidstone.gov.uk http://www.maidstone.gov.uk
Adrian Hall
email: adrian@hottub.org
+
private String PG_PASSWORD;
private String PG_DATABASE;
private boolean PG_STATUS;
+ private boolean PG_AUTH; // true, then password auth used
public boolean CONNECTION_OK = true;
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 readOnly = false;
private String this_url;
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.
*
*/
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_url = new String(url);
PG_HOST = new String(host);
PG_STATUS = CONNECTION_BAD;
+ if(info.getProperty("auth") != null) {
+ PG_AUTH=true;
+ STARTUP_CODE=STARTUP_PASS;
+ } else {
+ STARTUP_CODE=STARTUP_USER;
+ }
+
try
{
pg_stream = new PG_Stream(host, port);
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(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) {
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;
}
*/
public SQLWarning getWarnings() throws SQLException
{
- return null; // We handle warnings as errors
+ return firstWarning;
}
/**
*/
public void clearWarnings() throws SQLException
{
- // Not handles since we handle wanrings as errors
+ firstWarning = null;
}
// **********************************************************
// 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
* objects.
case 'N': // Error Notification
msg = pg_stream.ReceiveString(4096);
PrintStream log = DriverManager.getLogStream();
- log.println(msg);
+ if(log!=null) log.println(msg);
+ addWarning(msg);
break;
case 'P': // Portal Name
String pname = pg_stream.ReceiveString(8192);
if (s != null)
{
- try
- {
- if (s.length() != 10)
- throw new NumberFormatException("Wrong Length!");
- int mon = Integer.parseInt(s.substring(0,2));
- int day = Integer.parseInt(s.substring(3,5));
- int yr = Integer.parseInt(s.substring(6));
- return new java.sql.Date(yr - 1900, mon -1, day);
- } catch (NumberFormatException e) {
- throw new SQLException("Bad Date Form: " + s);
+ try {
+ if (s.length() != 10)
+ throw new NumberFormatException("Wrong Length!");
+ int mon = Integer.parseInt(s.substring(0,2));
+ int day = Integer.parseInt(s.substring(3,5));
+ int yr = Integer.parseInt(s.substring(6));
+ if(connection.europeanDates) {
+ // We europeans prefer dd mm yyyy
+ int t = mon;
+ 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
}
public Timestamp getTimestamp(int columnIndex) throws SQLException
{
String s = getString(columnIndex);
- DateFormat df = DateFormat.getDateInstance();
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzz");
if (s != null)
{
- try
- {
- java.sql.Date d = (java.sql.Date)df.parse(s);
- return new Timestamp(d.getTime());
- } catch (ParseException e) {
- throw new SQLException("Bad Timestamp Format: " + s);
- }
+ int TZ = new Float(s.substring(19)).intValue();
+ TZ = TZ * 60 * 60 * 1000;
+ TimeZone zone = TimeZone.getDefault();
+ zone.setRawOffset(TZ);
+ String nm = zone.getID();
+ 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
}
/**