diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriter.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriter.java index 0fdbf6ae0c..2ddeffb553 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriter.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriter.java @@ -179,41 +179,49 @@ protected Object convertObjectValue(Object value, Column column) { String stringValue = (String)value; return parseTimestampTZ(column.getMappedTypeCode(), stringValue); } - + return value; } protected Datum parseTimestampTZ(int type, String value) { - Timestamp timestamp = null; - TimeZone timezone = null; - try { - // Try something like: 2015-11-20 13:37:44.000000000 - timestamp = Timestamp.valueOf(value); - timezone = TimeZone.getDefault(); - } - catch (Exception ex) { - log.debug("Failed to convert value to timestamp.", ex); - // Now expecting something like: 2015-11-20 13:37:44.000000000 +08:00 - int split = value.lastIndexOf(" "); - String timestampString = value.substring(0, split).trim(); - String timezoneString = value.substring(split).trim(); - - timestamp = Timestamp.valueOf(timestampString); - - timezone = ((AbstractDatabasePlatform)platform).getTimeZone(timezoneString); - // Even though we provide the timezone to the Oracle driver, apparently - // the timestamp component needs to actually be in UTC. - if (type == OracleTypes.TIMESTAMPTZ) { - timestamp = toUTC(timestamp, timezone); - } + if (value == null || StringUtils.isEmpty(value.trim())) { + return null; } - Calendar timezoneCalender = Calendar.getInstance(); - timezoneCalender.setTimeZone(timezone); - timezoneCalender.setTime(timestamp); - JdbcSqlTransaction jdbcTransaction = (JdbcSqlTransaction) transaction; - Connection c = jdbcTransaction.getConnection(); try { + Timestamp timestamp = null; + TimeZone timezone = null; + try { + // Try something like: 2015-11-20 13:37:44.000000000 + timestamp = Timestamp.valueOf(value.trim()); + timezone = TimeZone.getDefault(); + } + catch (Exception ex) { + log.debug("Failed to convert value to timestamp.", ex); + // Now expecting something like: 2015-11-20 13:37:44.000000000 +08:00 + int split = value.lastIndexOf(" "); + String timestampString = value.substring(0, split).trim(); + if (timestampString.endsWith(".")) { // Cover case where triggers would export format like "2007-01-02 03:20:10." + timestampString = timestampString.substring(0, timestampString.length()-1); + } + String timezoneString = value.substring(split).trim(); + + timestamp = Timestamp.valueOf(timestampString); + + timezone = ((AbstractDatabasePlatform)platform).getTimeZone(timezoneString); + // Even though we provide the timezone to the Oracle driver, apparently + // the timestamp component needs to actually be in UTC. + if (type == OracleTypes.TIMESTAMPTZ) { + timestamp = toUTC(timestamp, timezone); + } + } + Calendar timezoneCalender = Calendar.getInstance(); + timezoneCalender.setTimeZone(timezone); + timezoneCalender.setTime(timestamp); + + JdbcSqlTransaction jdbcTransaction = (JdbcSqlTransaction) transaction; + Connection c = jdbcTransaction.getConnection(); + Connection oracleConnection = jdbcExtractor.getNativeConnection(c); Datum ts = null; if (type == OracleTypes.TIMESTAMPTZ) { @@ -222,16 +230,16 @@ protected Datum parseTimestampTZ(int type, String value) { ts = new TIMESTAMPLTZ(oracleConnection, timestamp); } return ts; - } catch (SQLException ex) { + } catch (Exception ex) { log.info("Failed to convert '" + value + "' to TIMESTAMPTZ." ); throw platform.getSqlTemplate().translate(ex); } } - + public Timestamp toUTC(Timestamp timestamp, TimeZone timezone) { int nanos = timestamp.getNanos(); timestamp.setNanos(0); - + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"); dateFormat.setTimeZone(timezone); Date date; @@ -241,7 +249,7 @@ public Timestamp toUTC(Timestamp timestamp, TimeZone timezone) { log.info("Failed to parse '" + timestamp + "'"); throw platform.getSqlTemplate().translate(ex); } - + Timestamp utcTimestamp = new Timestamp(date.getTime()); utcTimestamp.setNanos(nanos); return utcTimestamp; @@ -467,7 +475,7 @@ protected void buildBulkInsertProcedure(Table table) { ddl.append(String.format("%s(i), \n", variable)); } ddl.replace(ddl.length()-3, ddl.length(), ");\n"); - + ddl.append(String.format("exception \n")); ddl.append(String.format(" when dml_errors then \n")); ddl.append(String.format(" for i in 1 .. SQL%%BULK_EXCEPTIONS.count loop \n")); @@ -478,7 +486,7 @@ protected void buildBulkInsertProcedure(Table table) { ddl.append(String.format(" o_errors(o_errors.count) := SQL%%BULK_EXCEPTIONS(i).ERROR_INDEX; \n")); ddl.append(String.format(" end loop; \n")); ddl.append(String.format("end %s; ", procedureName)); - + if (log.isDebugEnabled()) { log.debug(ddl.toString()); } diff --git a/symmetric-client/src/test/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriterTest.java b/symmetric-client/src/test/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriterTest.java index 98a20775bf..4ac1f662f8 100644 --- a/symmetric-client/src/test/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriterTest.java +++ b/symmetric-client/src/test/java/org/jumpmind/symmetric/io/OracleBulkDatabaseWriterTest.java @@ -168,6 +168,44 @@ public void testInsertTimestampTZ_timestampWithTimeZone() throws Exception { } } + @Test + public void testInsertTimestampTZ_timestampWithTimeZoneNull() throws Exception { + if (platform != null && platform instanceof OracleDatabasePlatform) { + + NativeJdbcExtractor jdbcExtractor = new CommonsDbcpNativeJdbcExtractor(); + + platform.getSqlTemplate().update("truncate table test_bulkload_table_1"); + + List datas = new ArrayList(); + + String id = getNextId(); + + String[] values = { id, "string2", "string not null2", "char2", + "char not null2", "2007-01-02 03:20:10.000", "2007-02-03 04:05:06.000", "0", + "47", "67.89", "-0.0747663", "2007-01-02 03:20:10. -08:00", + "", + " ", + null }; + CsvData data = new CsvData(DataEventType.INSERT, values); + datas.add(data); + + long count = writeData(new TableCsvData(platform.getTableFromCache( + "test_bulkload_table_1", false), datas)); + + Map rowData = queryForRow(id); + DataSource datasource = (DataSource)platform.getDataSource(); + Connection connection = datasource.getConnection(); + Connection oracleConnection = jdbcExtractor.getNativeConnection(connection); + + checkTimestampTZ(rowData.get("TIMESTAMPTZ0_VALUE"), oracleConnection, "2007-01-02 03:20:10.0 -8:00"); + Assert.assertNull(rowData.get("TIMESTAMPTZ3_VALUE")); + Assert.assertNull(rowData.get("TIMESTAMPTZ6_VALUE")); + Assert.assertNull(rowData.get("TIMESTAMPTZ9_VALUE")); + + Assert.assertEquals(count, countRows("test_bulkload_table_1")); + } + } + @Test public void testInsertTimestampTZ_timestampWithLocalTimeZone() throws Exception { if (platform != null && platform instanceof OracleDatabasePlatform) {