Commit 0651a579 authored by Bruce Momjian's avatar Bruce Momjian

Backed out:

---------------------------------------------------------------------------

Attached is a set of patches for a couple of bugs dealing with
timestamps in JDBC.

Bug#1) Incorrect timestamp stored in DB if client timezone different
than DB.
parent 526427f6
...@@ -310,11 +310,12 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -310,11 +310,12 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* @param x the parameter value * @param x the parameter value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
private static final SimpleDateFormat DF1 = new SimpleDateFormat("yyyy-MM-dd");
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
{ {
set(parameterIndex, DF1.format(x)); SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
set(parameterIndex, df.format(x));
// The above is how the date should be handled. // The above is how the date should be handled.
// //
// However, in JDK's prior to 1.1.6 (confirmed with the // However, in JDK's prior to 1.1.6 (confirmed with the
...@@ -348,17 +349,9 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -348,17 +349,9 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* @param x the parameter value * @param x the parameter value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
private static SimpleDateFormat DF2 = getDF2();
private static SimpleDateFormat getDF2() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
return sdf;
}
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
{ {
StringBuffer strBuf = new StringBuffer("'"); set(parameterIndex, "'" + x.toString() + "'");
strBuf.append(DF2.format(x)).append('.').append(x.getNanos()/10000000).append("+00'");
set(parameterIndex, strBuf.toString());
} }
/** /**
......
...@@ -412,8 +412,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu ...@@ -412,8 +412,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
String s = getString(columnIndex); String s = getString(columnIndex);
if(s==null) if(s==null)
return null; return null;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try { try {
return new java.sql.Date(DF5.parse(s).getTime()); return new java.sql.Date(df.parse(s).getTime());
} catch (ParseException e) { } catch (ParseException e) {
throw new PSQLException("postgresql.res.baddate",new Integer(e.getErrorOffset()),s); throw new PSQLException("postgresql.res.baddate",new Integer(e.getErrorOffset()),s);
} }
...@@ -456,59 +457,30 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu ...@@ -456,59 +457,30 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
* @return the column value; null if SQL NULL * @return the column value; null if SQL NULL
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
private static final SimpleDateFormat DF1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSzzzzzzzzz");
private static final SimpleDateFormat DF2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzzzzzzzz");
private static final SimpleDateFormat DF3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
private static final SimpleDateFormat DF4 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat DF5 = new SimpleDateFormat("yyyy-MM-dd");
public Timestamp getTimestamp(int columnIndex) throws SQLException public Timestamp getTimestamp(int columnIndex) throws SQLException
{ {
String s = getString(columnIndex); String s = getString(columnIndex);
if(s==null) if(s==null)
return null; return null;
boolean subsecond; // This works, but it's commented out because Michael Stephenson's
//if string contains a '.' we have fractional seconds // solution is better still:
if (s.indexOf('.') == -1) { //SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
subsecond = false;
} else { // Michael Stephenson's solution:
subsecond = true;
}
//here we are modifying the string from ISO format to a format java can understand
//java expects timezone info as 'GMT-08:00' instead of '-08' in postgres ISO format
//and java expects three digits if fractional seconds are present instead of two for postgres
//so this code strips off timezone info and adds on the GMT+/-...
//as well as adds a third digit for partial seconds if necessary
StringBuffer strBuf = new StringBuffer(s);
char sub = strBuf.charAt(strBuf.length()-3);
if (sub == '+' || sub == '-') {
strBuf.setLength(strBuf.length()-3);
if (subsecond) {
strBuf = strBuf.append('0').append("GMT").append(s.substring(s.length()-3, s.length())).append(":00");
} else {
strBuf = strBuf.append("GMT").append(s.substring(s.length()-3, s.length())).append(":00");
}
} else if (subsecond) {
strBuf = strBuf.append('0');
}
s = strBuf.toString();
SimpleDateFormat df = null; SimpleDateFormat df = null;
if (s.length()>21 && s.indexOf('.') != -1) {
if (s.length()>23 && subsecond) { df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSzzz");
df = DF1; } else if (s.length()>19 && s.indexOf('.') == -1) {
} else if (s.length()>23 && !subsecond) { df = new SimpleDateFormat("yyyy-MM-dd HH:MM:sszzz");
df = DF2; } else if (s.length()>19 && s.indexOf('.') != -1) {
} else if (s.length()>10 && subsecond) { df = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss.SS");
df = DF3; } else if (s.length()>10 && s.length()<=18) {
} else if (s.length()>10 && !subsecond) { df = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss");
df = DF4;
} else { } else {
df = DF5; df = new SimpleDateFormat("yyyy-MM-dd");
} }
try { try {
return new Timestamp(df.parse(s).getTime()); return new Timestamp(df.parse(s).getTime());
} catch(ParseException e) { } catch(ParseException e) {
......
...@@ -310,11 +310,12 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -310,11 +310,12 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* @param x the parameter value * @param x the parameter value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
private static final SimpleDateFormat DF1 = new SimpleDateFormat("yyyy-MM-dd");
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
{ {
set(parameterIndex, DF1.format(x)); SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
set(parameterIndex, df.format(x));
// The above is how the date should be handled. // The above is how the date should be handled.
// //
// However, in JDK's prior to 1.1.6 (confirmed with the // However, in JDK's prior to 1.1.6 (confirmed with the
...@@ -348,17 +349,9 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -348,17 +349,9 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* @param x the parameter value * @param x the parameter value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
private static SimpleDateFormat DF2 = getDF2();
private static SimpleDateFormat getDF2() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
return sdf;
}
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
{ {
StringBuffer strBuf = new StringBuffer("'"); set(parameterIndex, "'" + x.toString() + "'");
strBuf.append(DF2.format(x)).append('.').append(x.getNanos()/10000000).append("+00'");
set(parameterIndex, strBuf.toString());
} }
/** /**
......
...@@ -415,8 +415,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu ...@@ -415,8 +415,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
String s = getString(columnIndex); String s = getString(columnIndex);
if(s==null) if(s==null)
return null; return null;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try { try {
return new java.sql.Date(DF5.parse(s).getTime()); return new java.sql.Date(df.parse(s).getTime());
} catch (ParseException e) { } catch (ParseException e) {
throw new PSQLException("postgresql.res.baddate",new Integer(e.getErrorOffset()),s); throw new PSQLException("postgresql.res.baddate",new Integer(e.getErrorOffset()),s);
} }
...@@ -459,66 +460,47 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu ...@@ -459,66 +460,47 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
* @return the column value; null if SQL NULL * @return the column value; null if SQL NULL
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
private static final SimpleDateFormat DF1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSzzzzzzzzz");
private static final SimpleDateFormat DF2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzzzzzzzz");
private static final SimpleDateFormat DF3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
private static final SimpleDateFormat DF4 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat DF5 = new SimpleDateFormat("yyyy-MM-dd");
public Timestamp getTimestamp(int columnIndex) throws SQLException public Timestamp getTimestamp(int columnIndex) throws SQLException
{ {
String s = getString(columnIndex); String s = getString(columnIndex);
if(s==null) if(s==null)
return null; return null;
boolean subsecond; // This works, but it's commented out because Michael Stephenson's
//if string contains a '.' we have fractional seconds // solution is better still:
if (s.indexOf('.') == -1) { //SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
subsecond = false; // Modification by Jan Thomae
} else { String sub = s.substring(s.length() - 3, s.length()-2);
subsecond = true; if (sub.equals("+") || sub.equals("-")) {
} s = s.substring(0, s.length()-3) + "GMT"+ s.substring(s.length()-3, s.length())+":00";
//here we are modifying the string from ISO format to a format java can understand
//java expects timezone info as 'GMT-08:00' instead of '-08' in postgres ISO format
//and java expects three digits if fractional seconds are present instead of two for postgres
//so this code strips off timezone info and adds on the GMT+/-...
//as well as adds a third digit for partial seconds if necessary
StringBuffer strBuf = new StringBuffer(s);
char sub = strBuf.charAt(strBuf.length()-3);
if (sub == '+' || sub == '-') {
strBuf.setLength(strBuf.length()-3);
if (subsecond) {
strBuf = strBuf.append('0').append("GMT").append(s.substring(s.length()-3, s.length())).append(":00");
} else {
strBuf = strBuf.append("GMT").append(s.substring(s.length()-3, s.length())).append(":00");
}
} else if (subsecond) {
strBuf = strBuf.append('0');
} }
// -------
s = strBuf.toString(); // Michael Stephenson's solution:
SimpleDateFormat df = null; SimpleDateFormat df = null;
if (s.length()>23 && subsecond) { // Modification by Jan Thomae
df = DF1; if (s.length()>27) {
} else if (s.length()>23 && !subsecond) { df = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzzzzzzzz");
df = DF2; } else
} else if (s.length()>10 && subsecond) { // -------
df = DF3; if (s.length()>21 && s.indexOf('.') != -1) {
} else if (s.length()>10 && !subsecond) { df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSzzz");
df = DF4; } else if (s.length()>19 && s.indexOf('.') == -1) {
df = new SimpleDateFormat("yyyy-MM-dd HH:MM:sszzz");
} else if (s.length()>19 && s.indexOf('.') != -1) {
df = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss.SS");
} else if (s.length()>10 && s.length()<=18) {
df = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss");
} else { } else {
df = DF5; df = new SimpleDateFormat("yyyy-MM-dd");
} }
try { try {
return new Timestamp(df.parse(s).getTime()); return new Timestamp(df.parse(s).getTime());
} catch(ParseException e) { } catch(ParseException e) {
throw new PSQLException("postgresql.res.badtimestamp",new Integer(e.getErrorOffset()),s); throw new PSQLException("postgresql.res.badtimestamp",new Integer(e.getErrorOffset()),s);
} }
} }
/** /**
* A column value can be retrieved as a stream of ASCII characters * A column value can be retrieved as a stream of ASCII characters
......
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