View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0001286 | SymmetricDS | Bug | public | 2013-06-18 06:51 | 2014-10-27 15:52 |
| Reporter | sngkw | Assigned To | chenson | ||
| Priority | normal | ||||
| Status | closed | Resolution | fixed | ||
| Product Version | 3.3.6 | ||||
| Target Version | 3.6.11 | Fixed in Version | 3.6.11 | ||
| Summary | 0001286: Failed to create trigger when table contains timestamp with time zone column in Oracle | ||||
| Description | Similar to 0000615: When a timestamp with time zone column is part of a primary key or part of a table w.out a primary key, then the trigger fails to create. But even we have a primary key, it still fails. We are using Oracle 11g and 11g driver. | ||||
| Tags | No tags attached. | ||||
|
|
What is the error? |
|
|
Can a timestamp with time zone be part of a primary key? I get this: Error: ORA-02329: column of datatype TIME/TIMESTAMP WITH TIME ZONE cannot be unique or a primary key SQLState: 99999 ErrorCode: 2329 Position: 103 |
|
|
|
|
|
The log shows the following: 11:54:11 AM CST ERROR [TriggerRouterService] [server-job-19] Failed to retrieve tables for trigger with id of VAT 11:54:11 AM CST ERROR [TriggerRouterService] [server-job-19] Could not find any database tables matching 'VAT' in the datasource that is configured 11:54:11 AM CST INFO [TriggerRouterService] [server-job-19] Done synchronizing triggers These are the column definitions in VAT, ID is primary key ID NUMBER(38,0) CODE VARCHAR2(20 CHAR) CREATED_BY VARCHAR2(300 CHAR) CREATED_DATE DATE MODIFIED_BY VARCHAR2(300 CHAR) MODIFIED_DATE TIMESTAMP(6) WITH LOCAL TIME ZONE |
|
|
This happens when the table can't be found in the database. |
|
|
It is able to find the table by Auto Create trigger function. But when I try to link with router, exception occurs. When I changed the data type from TIMESTAMP(6) WITH LOCAL TIME ZONE to TIMESTAMP(6). The exception does not occur. |
|
|
Oracle JDBC driver returns SQL type -102 for column type "TIMESTAMP(6) WITH LOCAL TIME ZONE". SymmetricDS handles SQL type -101 (TIMESTAMP(6) WITH TIME ZONE), but not SQL type -102. Attached is a patch. I have tested with Oracle 9 (it's the same in newer versions), Oracle JDBC 11 and MySQL 5.5. Oracle table: create table test( ID NUMBER(38) not null, CODE VARCHAR2(20), CREATED_BY VARCHAR2(300), CREATED_DATE DATE, MODIFIED_BY VARCHAR2(300), MODIFIED_DATE TIMESTAMP(6) WITH LOCAL TIME ZONE, MODIFIED_DATE2 TIMESTAMP(6) WITH TIME ZONE, MODIFIED_DATE3 TIMESTAMP, PRIMARY KEY(ID) ) MySQL table: create table test( ID INTEGER NOT NULL, CODE VARCHAR(20), CREATED_BY VARCHAR(300), CREATED_DATE DATE, MODIFIED_BY VARCHAR(300), MODIFIED_DATE TIMESTAMP, MODIFIED_DATE2 TIMESTAMP, MODIFIED_DATE3 TIMESTAMP, PRIMARY KEY(ID) ) |
|
|
oracleTimestampltz.diff (11,213 bytes)
Index: symmetric-oracle/src/main/java/org/jumpmind/symmetric/io/data/writer/OracleBulkDatabaseWriter.java
===================================================================
--- symmetric-oracle/src/main/java/org/jumpmind/symmetric/io/data/writer/OracleBulkDatabaseWriter.java (revision 7565)
+++ symmetric-oracle/src/main/java/org/jumpmind/symmetric/io/data/writer/OracleBulkDatabaseWriter.java (working copy)
@@ -200,6 +200,8 @@
return "varchar(4000)";
case Types.DATE:
case Types.TIME:
+ case OracleTypes.TIMESTAMPLTZ:
+ return "timestamp with local time zone";
case OracleTypes.TIMESTAMPTZ:
return "timestamp with time zone";
case Types.TIMESTAMP:
@@ -227,6 +229,7 @@
case Types.DATE:
case Types.TIME:
case OracleTypes.TIMESTAMPTZ:
+ case OracleTypes.TIMESTAMPLTZ:
case Types.TIMESTAMP:
return String.format("%s_%s_t", procedurePrefix, "timestamp").toUpperCase();
case Types.NUMERIC:
Index: symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriterConflictResolver.java
===================================================================
--- symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriterConflictResolver.java (revision 7565)
+++ symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriterConflictResolver.java (working copy)
@@ -247,7 +247,7 @@
Date loadingTs = null;
Date existingTs = null;
- if (column.getMappedTypeCode() == -101) {
+ if (column.getMappedTypeCode() == -101 || column.getMappedTypeCode() == -102) {
// Get the existingTs with timezone
String existingStr = writer.getTransaction().queryForObject(sql, String.class,
objectValues);
Index: symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleTriggerTemplate.java
===================================================================
--- symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleTriggerTemplate.java (revision 7565)
+++ symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleTriggerTemplate.java (working copy)
@@ -36,6 +36,7 @@
geometryColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then to_clob('') else '\"'||replace(replace(SDO_UTIL.TO_WKTGEOMETRY($(tableAlias).\"$(columnName)\"),'\\','\\\\'),'\"','\\\"')||'\"' end";
numberColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', '\"'||cast($(tableAlias).\"$(columnName)\" as number("+symmetricDialect.getTemplateNumberPrecisionSpec()+"))||'\"')" ;
datetimeColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', concat(concat('\"',to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS.FF3')),'\"'))" ;
+ dateTimeWithLocalTimeZoneColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', concat(concat('\"',to_char(cast($(tableAlias).\"$(columnName)\" as timestamp), 'YYYY-MM-DD HH24:MI:SS.FF')),'\"'))" ;
dateTimeWithTimeZoneColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', concat(concat('\"',to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM')),'\"'))" ;
timeColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', concat(concat('\"',to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS')),'\"'))" ;
dateColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', concat(concat('\"',to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS')),'\"'))" ;
Index: symmetric-db/src/main/java/org/jumpmind/db/model/TypeMap.java
===================================================================
--- symmetric-db/src/main/java/org/jumpmind/db/model/TypeMap.java (revision 7565)
+++ symmetric-db/src/main/java/org/jumpmind/db/model/TypeMap.java (working copy)
@@ -88,6 +88,8 @@
public static final String TIMESTAMP = "TIMESTAMP";
public static final String TIMESTAMPTZ = "TIMESTAMPTZ";
+
+ public static final String TIMESTAMPLTZ = "TIMESTAMPLTZ";
/** The string representation of the {@link java.sql.Types#TINYINT} constant. */
public static final String TINYINT = "TINYINT";
@@ -150,6 +152,7 @@
registerJdbcType(Types.VARBINARY, VARBINARY, JdbcTypeCategoryEnum.BINARY);
registerJdbcType(Types.VARCHAR, VARCHAR, JdbcTypeCategoryEnum.TEXTUAL);
registerJdbcType(-101, TIMESTAMPTZ, JdbcTypeCategoryEnum.DATETIME);
+ registerJdbcType(-102, TIMESTAMPLTZ, JdbcTypeCategoryEnum.DATETIME);
// only available in JDK 1.4 and above:
if (PlatformUtils.supportsJava14JdbcTypes())
Index: symmetric-db/src/main/java/org/jumpmind/db/model/Column.java
===================================================================
--- symmetric-db/src/main/java/org/jumpmind/db/model/Column.java (revision 7565)
+++ symmetric-db/src/main/java/org/jumpmind/db/model/Column.java (working copy)
@@ -654,7 +654,7 @@
}
public boolean isTimestampWithTimezone() {
- return jdbcTypeCode == -101 || (jdbcTypeName != null && jdbcTypeName.equals("timestamptz"));
+ return jdbcTypeCode == -101 || jdbcTypeCode == -102 || (jdbcTypeName != null && jdbcTypeName.equals("timestamptz"));
}
public boolean containsJdbcTypes() {
Index: symmetric-db/src/main/java/org/jumpmind/db/platform/oracle/OracleDmlStatement.java
===================================================================
--- symmetric-db/src/main/java/org/jumpmind/db/platform/oracle/OracleDmlStatement.java (revision 7565)
+++ symmetric-db/src/main/java/org/jumpmind/db/platform/oracle/OracleDmlStatement.java (working copy)
@@ -43,6 +43,9 @@
if (columns[i].getMappedTypeCode() == -101) {
sql.append("TO_TIMESTAMP_TZ(?, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM')")
.append(",");
+ } else if (columns[i].getMappedTypeCode() == -102) {
+ sql.append("CAST(TO_TIMESTAMP_TZ(?, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM') AS TIMESTAMP WITH TIME ZONE)")
+ .append(",");
} else if (columns[i].getJdbcTypeName() != null && columns[i].getJdbcTypeName().toUpperCase().contains(TypeMap.GEOMETRY)) {
sql.append("SYM_WKT2GEOM(?)").append(",");
} else {
@@ -63,7 +66,7 @@
if (nullValues[i]) {
sql.append(quote).append(columns[i].getName()).append(quote).append(" is NULL")
.append(separator);
- } else if (columns[i].getMappedTypeCode() == -101) {
+ } else if (columns[i].getMappedTypeCode() == -101 || columns[i].getMappedTypeCode() == -102) {
sql.append(quote).append(columns[i].getName()).append(quote)
.append(" = TO_TIMESTAMP_TZ(?, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM')")
.append(separator);
Index: symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java
===================================================================
--- symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java (revision 7565)
+++ symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java (working copy)
@@ -34,6 +34,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.TimeZone;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
@@ -501,7 +502,14 @@
try {
return Timestamp.valueOf(value);
} catch (IllegalArgumentException ex) {
- return FormatUtils.parseDate(value, FormatUtils.TIMESTAMP_PATTERNS);
+ try {
+ return FormatUtils.parseDate(value, FormatUtils.TIMESTAMP_PATTERNS);
+ } catch (Exception e) {
+ int split = value.lastIndexOf(" ");
+ return FormatUtils.parseDate(value.substring(0, split).trim(),
+ FormatUtils.TIMESTAMP_PATTERNS,
+ TimeZone.getTimeZone(value.substring(split).trim()));
+ }
}
} else if (type == Types.TIME) {
return FormatUtils.parseDate(value, FormatUtils.TIME_PATTERNS);
Index: symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java
===================================================================
--- symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java (revision 7565)
+++ symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java (working copy)
@@ -76,6 +76,8 @@
protected String dateColumnTemplate;
protected String dateTimeWithTimeZoneColumnTemplate;
+
+ protected String dateTimeWithLocalTimeZoneColumnTemplate;
protected String geometryColumnTemplate;
@@ -667,6 +669,11 @@
.isNotBlank(this.dateTimeWithTimeZoneColumnTemplate)) {
templateToUse = this.dateTimeWithTimeZoneColumnTemplate;
break;
+ } else if (column.getMappedType().equals(TypeMap.TIMESTAMPLTZ)
+ && StringUtils
+ .isNotBlank(this.dateTimeWithLocalTimeZoneColumnTemplate)) {
+ templateToUse = this.dateTimeWithLocalTimeZoneColumnTemplate;
+ break;
}
}
Index: symmetric-jdbc/src/main/java/org/jumpmind/db/sql/JdbcSqlTemplate.java
===================================================================
--- symmetric-jdbc/src/main/java/org/jumpmind/db/sql/JdbcSqlTemplate.java (revision 7565)
+++ symmetric-jdbc/src/main/java/org/jumpmind/db/sql/JdbcSqlTemplate.java (working copy)
@@ -499,6 +499,8 @@
obj = rs.getTimestamp(index);
} else if (className != null && "oracle.sql.TIMESTAMPTZ".equals(className)) {
obj = rs.getString(index);
+ } else if (className != null && "oracle.sql.TIMESTAMPLTZ".equals(className)) {
+ obj = rs.getString(index);
} else if (className != null && className.startsWith("oracle.sql.DATE")) {
String metaDataClassName = metaData.getColumnClassName(index);
if ("java.sql.Timestamp".equals(metaDataClassName)
@@ -882,7 +884,7 @@
}
protected int verifyArgType(Object arg, int argType) {
- if (argType == -101 || argType == Types.OTHER) {
+ if (argType == -101 || argType == -102 || argType == Types.OTHER) {
return SqlTypeValue.TYPE_UNKNOWN;
} else if ((argType == Types.INTEGER && arg instanceof BigInteger) ||
(argType == Types.BIGINT && arg instanceof BigDecimal)) {
|
|
|
ah. timestamp with "local" timezone. somehow i missed the local last time i looked at this issue. thanks for the patch. |
|
SymmetricDS: master f454c5e8 2014-10-26 20:10:26 Details Diff |
0001286: Failed to create trigger when table contains timestamp with time zone column in Oracle |
Affected Issues 0001286 |
|
| mod - symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleTriggerTemplate.java | Diff File | ||
| mod - symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java | Diff File | ||
| mod - symmetric-db/src/main/java/org/jumpmind/db/model/TypeMap.java | Diff File | ||
| mod - symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java | Diff File | ||
| mod - symmetric-jdbc/src/main/java/org/jumpmind/db/sql/JdbcSqlTemplate.java | Diff File | ||
| mod - symmetric-oracle/src/main/java/org/jumpmind/symmetric/io/data/writer/OracleBulkDatabaseWriter.java | Diff File | ||
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2013-06-18 06:51 | sngkw | New Issue | |
| 2013-06-19 12:03 | chenson | Note Added: 0000278 | |
| 2013-06-19 13:19 | chenson | Note Added: 0000279 | |
| 2013-06-20 00:39 | chenson | Project | SymmetricDS Pro => SymmetricDS |
| 2013-06-20 02:19 | sngkw | File Added: trigger.jpg | |
| 2013-06-20 02:22 | sngkw | Note Added: 0000286 | |
| 2013-06-22 19:00 | chenson | Note Added: 0000287 | |
| 2013-06-24 03:01 | sngkw | Note Added: 0000289 | |
| 2013-07-24 02:48 | snpe | Note Added: 0000353 | |
| 2013-07-24 02:49 | snpe | File Added: oracleTimestampltz.diff | |
| 2013-07-24 16:50 | chenson | Note Added: 0000355 | |
| 2013-07-24 16:51 | chenson | Target Version | => 3.5.1 |
| 2014-10-27 00:11 | chenson | Fixed in Version | => 3.6.11 |
| 2014-10-27 00:11 | chenson | Target Version | 3.5.1 => 3.6.11 |
| 2014-10-27 00:11 | chenson | Status | new => resolved |
| 2014-10-27 00:11 | chenson | Resolution | open => fixed |
| 2014-10-27 00:11 | chenson | Assigned To | => chenson |
| 2014-10-27 01:00 | chenson | Changeset attached | => SymmetricDS trunk r8837 |
| 2014-10-27 01:00 | chenson | Changeset attached | => SymmetricDS 3.6 r8838 |
| 2014-10-27 15:52 | chenson | Status | resolved => closed |
| 2015-07-31 01:49 | chenson | Changeset attached | => SymmetricDS master f454c5e8 |