Changeset: b98a0fee73f3 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b98a0fee73f3 Modified Files: java/src/nl/cwi/monetdb/jdbc/MonetConnection.java Branch: default Log Message:
Merge with Apr2011 branch. diffs (truncated from 701 to 300 lines): diff --git a/java/ChangeLog.Apr2011 b/java/ChangeLog.Apr2011 --- a/java/ChangeLog.Apr2011 +++ b/java/ChangeLog.Apr2011 @@ -1,3 +1,8 @@ # ChangeLog file for java # This file is updated with Maddlog +* Wed May 11 2011 Fabian Groffen <fab...@cwi.nl> +- Insertion via PreparedStatement and retrieval via ResultSet of timestamp + and time fields with and without timezones was improved to better + respect timezones, as partly indicated in bug #2781. + diff --git a/java/Makefile.ag b/java/Makefile.ag --- a/java/Makefile.ag +++ b/java/Makefile.ag @@ -27,7 +27,7 @@ ant_distjdbc = { COND = HAVE_JAVAJDBC DIR = datadir/monetdb/lib - FILES = monetdb-1.6-mcl.jar monetdb-1.19-jdbc.jar jdbcclient.jar + FILES = monetdb-1.6-mcl.jar monetdb-1.20-jdbc.jar jdbcclient.jar } ant_distmerocontrol = { diff --git a/java/build.properties b/java/build.properties --- a/java/build.properties +++ b/java/build.properties @@ -19,7 +19,7 @@ # major release number JDBC_MAJOR=1 # minor release number -JDBC_MINOR=19 +JDBC_MINOR=20 # an additional identifying string JDBC_VER_SUFFIX=Magnistipula # the default port to connect on, if no port given when using SQL diff --git a/java/release.txt b/java/release.txt --- a/java/release.txt +++ b/java/release.txt @@ -1,8 +1,8 @@ RELEASE NOTES -MonetDB JDBC driver version 1.19 (Magnistipula/MCL-1.6) +MonetDB JDBC driver version 1.20 (Magnistipula/MCL-1.6) Fabian Groffen <fabian.grof...@cwi.nl> -Release date: 2011-04-05 +Release date: 2011-05-11 This JDBC driver is designed for use with MonetDB, a main-memory diff --git a/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java b/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java --- a/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java +++ b/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java @@ -252,7 +252,8 @@ setAutoCommit(true); // set our time zone on the server Calendar cal = Calendar.getInstance(); - int offset = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000); + int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); + offset /= (60 * 1000); // milliseconds to minutes String tz = offset < 0 ? "-" : "+"; tz += (Math.abs(offset) / 60 < 10 ? "0" : "") + (Math.abs(offset) / 60) + ":"; offset -= (offset / 60) * 60; diff --git a/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java b/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java --- a/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java +++ b/java/src/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java @@ -69,10 +69,16 @@ /** Format of a timestamp with RFC822 time zone */ final SimpleDateFormat mTimestampZ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ"); + /** Format of a timestamp */ + final SimpleDateFormat mTimestamp = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); /** Format of a time with RFC822 time zone */ final SimpleDateFormat mTimeZ = new SimpleDateFormat("HH:mm:ss.SSSZ"); - /** Format of a date used by Mserver */ + /** Format of a time */ + final SimpleDateFormat mTime = + new SimpleDateFormat("HH:mm:ss.SSS"); + /** Format of a date used by mserver */ final SimpleDateFormat mDate = new SimpleDateFormat("yyyy-MM-dd"); @@ -652,7 +658,7 @@ public void setDate(int parameterIndex, java.sql.Date x) throws SQLException { - setValue(parameterIndex, "date '" + x.toString() + "'"); + setDate(parameterIndex, x, null); } /** @@ -672,8 +678,12 @@ public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) throws SQLException { - mDate.setTimeZone(cal.getTimeZone()); - setValue(parameterIndex, "date '" + mDate.format(x) + "'"); + if (cal == null) { + setValue(parameterIndex, "date '" + x.toString() + "'"); + } else { + mDate.setTimeZone(cal.getTimeZone()); + setValue(parameterIndex, "date '" + mDate.format(x) + "'"); + } } /** @@ -1208,10 +1218,7 @@ * @throws SQLException if a database access error occurs */ public void setTime(int index, Time x) throws SQLException { - if (index < 1 || index > size) - throw new SQLException("No such parameter with index: " + index); - - setValue(index, monetdbType[index - 1] + " '" + x.toString() + "'"); + setTime(index, x, null); } /** @@ -1235,11 +1242,25 @@ if (index < 1 || index > size) throw new SQLException("No such parameter with index: " + index); - mTimeZ.setTimeZone(cal.getTimeZone()); - - String RFC822 = mTimeZ.format(x); - setValue(index, monetdbType[index - 1] + " '" + - RFC822.substring(0, 15) + ":" + RFC822.substring(15) + "'"); + boolean hasTimeZone = monetdbType[index - 1].endsWith("tz"); + if (hasTimeZone) { + // timezone shouldn't matter, since the server is timezone + // aware in this case + String RFC822 = mTimeZ.format(x); + setValue(index, "timetz '" + + RFC822.substring(0, 15) + ":" + RFC822.substring(15) + "'"); + } else { + // server is not timezone aware for this field, and no + // calendar given, since we told the server our timezone at + // connection creation, we can just write a plain timestamp + // here + if (cal == null) { + setValue(index, "time '" + x.toString() + "'"); + } else { + mTime.setTimeZone(cal.getTimeZone()); + setValue(index, "time '" + mTime.format(x) + "'"); + } + } } /** @@ -1254,10 +1275,7 @@ public void setTimestamp(int index, Timestamp x) throws SQLException { - if (index < 1 || index > size) - throw new SQLException("No such parameter with index: " + index); - - setValue(index, monetdbType[index - 1] + " '" + x.toString() + "'"); + setTimestamp(index, x, null); } /** @@ -1282,11 +1300,25 @@ if (index < 1 || index > size) throw new SQLException("No such parameter with index: " + index); - if (cal == null) cal = Calendar.getInstance(); - mTimestampZ.setTimeZone(cal.getTimeZone()); - String RFC822 = mTimestampZ.format(x); - setValue(index, monetdbType[index - 1] + " '" + - RFC822.substring(0, 26) + ":" + RFC822.substring(26) + "'"); + boolean hasTimeZone = monetdbType[index - 1].endsWith("tz"); + if (hasTimeZone) { + // timezone shouldn't matter, since the server is timezone + // aware in this case + String RFC822 = mTimestampZ.format(x); + setValue(index, "timestamptz '" + + RFC822.substring(0, 26) + ":" + RFC822.substring(26) + "'"); + } else { + // server is not timezone aware for this field, and no + // calendar given, since we told the server our timezone at + // connection creation, we can just write a plain timestamp + // here + if (cal == null) { + setValue(index, "timestamp '" + x.toString() + "'"); + } else { + mTimestamp.setTimeZone(cal.getTimeZone()); + setValue(index, "timestamp '" + mTimestamp.format(x) + "'"); + } + } } /** diff --git a/java/src/nl/cwi/monetdb/jdbc/MonetResultSet.java b/java/src/nl/cwi/monetdb/jdbc/MonetResultSet.java --- a/java/src/nl/cwi/monetdb/jdbc/MonetResultSet.java +++ b/java/src/nl/cwi/monetdb/jdbc/MonetResultSet.java @@ -24,6 +24,7 @@ import java.util.*; import java.math.*; import java.net.*; +import java.text.*; import nl.cwi.monetdb.mcl.parser.*; /** @@ -1587,6 +1588,12 @@ } // This behaviour is according table B-6 of Sun JDBC Specification 3.0 + private static SimpleDateFormat ts = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static SimpleDateFormat t = + new SimpleDateFormat("HH:mm:ss"); + private static SimpleDateFormat d = + new SimpleDateFormat("yyyy-MM-dd"); /** * Helper method which parses the date/time value for columns of type * TIME, DATE and TIMESTAMP. For the types CHAR, VARCHAR and @@ -1612,12 +1619,12 @@ if (col <= 0) throw new IllegalArgumentException("No valid column number given!"); - String monetDate; - if ((monetDate = getString(col)) == null) return(-1); - char[] monDate = monetDate.toCharArray(); - int pos = 0; - int tmp; + String monetDate = getString(col); + if (monetDate == null) + return(-1); + int nanos = 0; + TimeZone ptz = cal.getTimeZone(); // If we got a string type, set the datatype to the given // type so we attempt to parse it as the caller thinks it is. @@ -1629,118 +1636,90 @@ dataType = type; } - // we want to start from scratch - cal.clear(); + // we know whether we have a time with or without + // time zone if the monet type ends with "tz" + boolean hasTimeZone = types[col - 1].endsWith("tz"); - try { - switch(dataType) { - default: - throw new MCLParseException("unsupported data type", 0); + // it is important to parse the time in the given timezone in + // order to get a correct (UTC) time value, hence we need to + // parse it first + if (hasTimeZone) { + // MonetDB/SQL99: Sign TwoDigitHours : Minutes + ptz = TimeZone.getTimeZone("GMT" + + monetDate.substring( + monetDate.length() - 6, + monetDate.length())); + } + ts.setTimeZone(ptz); + t.setTimeZone(ptz); + d.setTimeZone(ptz); - case Types.DATE: - case Types.TIMESTAMP: - // parse the date YYYY-MM-DD if we have enough chars - if (monDate.length - pos < 10) break; - // year - tmp = 0; - tmp += getIntrinsicValue(monDate[pos], pos++) * 1000; - tmp += getIntrinsicValue(monDate[pos], pos++) * 100; - tmp += getIntrinsicValue(monDate[pos], pos++) * 10; - tmp += getIntrinsicValue(monDate[pos], pos++); - cal.set(Calendar.YEAR, tmp); - if (monDate[pos++] != '-') throw - new MCLParseException("expected '-'", pos - 1); - // month - tmp = 0; - tmp += getIntrinsicValue(monDate[pos], pos++) * 10; - tmp += getIntrinsicValue(monDate[pos], pos++); - cal.set(Calendar.MONTH, tmp - 1); - if (monDate[pos++] != '-') throw - new MCLParseException("expected '-'", pos - 1); - // day of month - tmp = 0; - tmp += getIntrinsicValue(monDate[pos], pos++) * 10; - tmp += getIntrinsicValue(monDate[pos], pos++); - cal.set(Calendar.DAY_OF_MONTH, tmp); - - if (dataType == Types.DATE || pos++ == monDate.length) - break; - case Types.TIME: - // parse the time HH:mm:ss.SSSSSSSS if we have enough chars - if (monDate.length - pos < 8) break; - // hour of day - tmp = 0; - tmp += getIntrinsicValue(monDate[pos], pos++) * 10; - tmp += getIntrinsicValue(monDate[pos], pos++); - cal.set(Calendar.HOUR_OF_DAY, tmp); _______________________________________________ Checkin-list mailing list Checkin-list@monetdb.org http://mail.monetdb.org/mailman/listinfo/checkin-list