Skip to content

Commit

Permalink
SYMMETRICDS-541 - Support SDO_GEOMETRY
Browse files Browse the repository at this point in the history
  • Loading branch information
chenson42 committed Mar 1, 2012
1 parent eae74cf commit 4a310ae
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 35 deletions.
Expand Up @@ -13,23 +13,20 @@ public OracleTriggerTemplate(ISymmetricDialect symmetricDialect) {
functionInstalledSql = "select count(*) from user_source where line = 1 and ((type = 'FUNCTION' and name=upper('$(functionName)')) or (name||'_'||type=upper('$(functionName)')))" ;
emptyColumnTemplate = "''" ;
stringColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, $(oracleToClob)'', '\"'||replace(replace($(oracleToClob)$(tableAlias).\"$(columnName)\",'\\','\\\\'),'\"','\\\"')||'\"')" ;
xmlColumnTemplate = null;
arrayColumnTemplate = null;
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(30,10))||'\"')" ;
datetimeColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', concat(concat('\"',to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS.FF3')),'\"'))" ;
dateTimeWithTimeZoneTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', concat(concat('\"',to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM')),'\"'))" ;
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')),'\"'))" ;
clobColumnTemplate = "decode(dbms_lob.getlength($(tableAlias).\"$(columnName)\"), null, to_clob(''), '\"'||replace(replace($(tableAlias).\"$(columnName)\",'\\','\\\\'),'\"','\\\"')||'\"')" ;
blobColumnTemplate = "decode(dbms_lob.getlength($(tableAlias).\"$(columnName)\"), null, to_clob(''), '\"'||sym_blob2clob($(tableAlias).\"$(columnName)\")||'\"')" ;
wrappedBlobColumnTemplate = null;
booleanColumnTemplate = "decode($(tableAlias).\"$(columnName)\", null, '', '\"'||cast($(tableAlias).\"$(columnName)\" as number(30,10))||'\"')" ;
triggerConcatCharacter = "||" ;
newTriggerValue = ":new" ;
oldTriggerValue = ":old" ;
oldColumnPrefix = "" ;
newColumnPrefix = "" ;
otherColumnTemplate = null;

functionTemplatesToInstall = new HashMap<String,String>();
functionTemplatesToInstall.put("blob2clob" ,
Expand Down Expand Up @@ -85,6 +82,22 @@ public OracleTriggerTemplate(ISymmetricDialect symmetricDialect) {
" end; " +
" end sym_pkg; " );

functionTemplatesToInstall.put("wkt2geom" ,
" CREATE OR REPLACE " +
" FUNCTION $(functionName)( " +
" clob_in IN CLOB) " +
" RETURN SDO_GEOMETRY " +
" AS " +
" v_out SDO_GEOMETRY := NULL; " +
" BEGIN " +
" IF clob_in IS NOT NULL THEN " +
" IF DBMS_LOB.GETLENGTH(clob_in) > 0 THEN " +
" v_out := SDO_GEOMETRY(clob_in); " +
" END IF; " +
" END IF; " +
" RETURN v_out; " +
" END $(functionName); ");

sqlTemplates = new HashMap<String,String>();
sqlTemplates.put("insertTriggerTemplate" ,
"create or replace trigger $(triggerName) \n" +
Expand Down
Expand Up @@ -17,7 +17,7 @@ public PostgreSqlTriggerTemplate(ISymmetricDialect symmetricDialect) {
arrayColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' || replace(replace(cast($(tableAlias).\"$(columnName)\" as varchar),$$\\$$,$$\\\\$$),'\"',$$\\\"$$) || '\"' end" ;
numberColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' || cast($(tableAlias).\"$(columnName)\" as varchar) || '\"' end" ;
datetimeColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' || to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS.US') || '\"' end" ;
dateTimeWithTimeZoneTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' || to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS.US ')||lpad(cast(extract(timezone_hour from $(tableAlias).\"$(columnName)\") as varchar),2,'0')||':'||lpad(cast(extract(timezone_minute from $(tableAlias).\"$(columnName)\") as varchar), 2, '0') || '\"' end" ;
dateTimeWithTimeZoneColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' || to_char($(tableAlias).\"$(columnName)\", 'YYYY-MM-DD HH24:MI:SS.US ')||lpad(cast(extract(timezone_hour from $(tableAlias).\"$(columnName)\") as varchar),2,'0')||':'||lpad(cast(extract(timezone_minute from $(tableAlias).\"$(columnName)\") as varchar), 2, '0') || '\"' end" ;
timeColumnTemplate = null;
dateColumnTemplate = null;
clobColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' || replace(replace($(tableAlias).\"$(columnName)\",$$\\$$,$$\\\\$$),'\"',$$\\\"$$) || '\"' end" ;
Expand Down
Expand Up @@ -30,6 +30,7 @@
import org.apache.commons.lang.StringUtils;
import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.model.TypeMap;
import org.jumpmind.symmetric.Version;
import org.jumpmind.symmetric.common.Constants;
import org.jumpmind.symmetric.io.data.DataEventType;
Expand Down Expand Up @@ -78,7 +79,9 @@ abstract public class AbstractTriggerTemplate {

protected String dateColumnTemplate;

protected String dateTimeWithTimeZoneTemplate;
protected String dateTimeWithTimeZoneColumnTemplate;

protected String geometryColumnTemplate;

protected String clobColumnTemplate;

Expand Down Expand Up @@ -647,26 +650,28 @@ protected ColumnString buildColumnString(String origTableAlias, String tableAlia
case Types.BIT:
templateToUse = booleanColumnTemplate;
break;
case Types.NULL:
case Types.OTHER:
templateToUse = this.otherColumnTemplate;
break;
case -101:
if (StringUtils.isNotBlank(this.dateTimeWithTimeZoneTemplate)) {
templateToUse = this.dateTimeWithTimeZoneTemplate;
break;
}
case Types.JAVA_OBJECT:
case Types.DISTINCT:
case Types.STRUCT:
case Types.REF:
case Types.DATALINK:
default:
if (column.getJdbcTypeName() != null
&& column.getJdbcTypeName().equalsIgnoreCase("interval")) {
templateToUse = numberColumnTemplate;
break;
if (column.getJdbcTypeName() != null) {
if (column.getJdbcTypeName().toUpperCase().equals(TypeMap.INTERVAL)) {
templateToUse = numberColumnTemplate;
break;
} else if (column.getJdbcTypeName().toUpperCase().contains(TypeMap.GEOMETRY)
&& StringUtils.isNotBlank(geometryColumnTemplate)) {
templateToUse = geometryColumnTemplate;
break;
} else if (column.getType().equals(TypeMap.TIMESTAMPTZ)
&& StringUtils.isNotBlank(this.dateTimeWithTimeZoneColumnTemplate)) {
templateToUse = this.dateTimeWithTimeZoneColumnTemplate;
break;
}

}

if (StringUtils.isBlank(templateToUse) && StringUtils.isNotBlank(this.otherColumnTemplate)) {
templateToUse = this.otherColumnTemplate;
break;
}

throw new NotImplementedException(column.getName() + " is of type "
+ column.getType() + " with JDBC type of "
+ column.getJdbcTypeName());
Expand Down
18 changes: 17 additions & 1 deletion symmetric/symmetric-core/src/main/resources/symmetric-schema.xml
Expand Up @@ -401,7 +401,7 @@

<table name="transform_table" description="Defines a data loader transformation which can be used to map arbitrary tables and columns to other tables and columns.">
<column name="transform_id" type="VARCHAR" size="50" required="true" primaryKey="true" description="Unique identifier of a specific transform." />
<column name="source_node_group_id" type="VARCHAR" size="50" required="true" primaryKey="true" description="The node group where data changes should be captured." />
<column name="source_node_group_id" type="VARCHAR" size="50" required="true" primaryKey="true" description="The node group where data changes are captured." />
<column name="target_node_group_id" type="VARCHAR" size="50" required="true" primaryKey="true" description="The node group where data changes will be sent." />
<column name="transform_point" type="VARCHAR" size="10" required="true" description="The point during the transport of captured data that a transform happens. Support values are EXTRACT or LOAD." />
<column name="source_catalog_name" type="VARCHAR" size="128" description="Optional name for the catalog the configured table is in." />
Expand All @@ -426,6 +426,22 @@
<column name="transform_order" type="INTEGER" required="true" default="1" description="Specifies the order in which to apply transforms if more than one target operation occurs."/>
</table>

<table name="conflict_resolver" description="Defines how conflicts in row data should be handled during the load process.">
<column name="conflict_id" type="VARCHAR" size="50" required="true" primaryKey="true" description="Unique identifier of a specific conflict resolver." />
<column name="source_node_group_id" type="VARCHAR" size="50" required="true" description="The node group where data changes are captured." />
<column name="target_node_group_id" type="VARCHAR" size="50" required="true" description="The node group where data changes will be sent." />
<column name="target_channel_id" type="VARCHAR" size="20" description="Optional id of a channel that this conflict resolver will be applied to. If left blank the resolver will applied to all tables specified by the target_table_name in the specified node group." />
<column name="target_catalog_name" type="VARCHAR" size="128" description="Optional name for the catalog a target table is in. Only use this if the target table is not in the default catalog." />
<column name="target_schema_name" type="VARCHAR" size="128" description="Optional name of the schema a target table is in. Only use this if the target table is not in the default schema." />
<column name="target_table_name" type="VARCHAR" size="128" description="Optional name for a target table that this resolver will be applied to. If left blank, the resolver will be for any table in the specified channel or specified node group." />
<column name="detector_type_update" type="VARCHAR" size="128" description="Possible values: row_missing, newer_timestamp_column, bigger_version_column, columns_changed_check, row_changed_check" />
<column name="resolver_type_update" type="VARCHAR" size="128" description="Possible values: newer_version_wins, last_sync_wins, manual" />
<column name="resolver_type_insert" type="VARCHAR" size="128" description="Possible values: newer_version_wins, last_sync_wins, ignore, blind_fallback, manual" />
<column name="resolver_type_delete" type="VARCHAR" size="128" description="ignore, manual" />
<column name="resolver_column_name" type="VARCHAR" size="128" description="The name of a column that is used by the chosen resolver should the resolver need a column to use in resolution" />
<column name="retry_count" type="INTEGER" required="true" default="-1" description="The number of times a batch in conflict will be retried before it is skipped. A setting of -1 means that the batch will be retried indefinitely." />
</table>

<!--
<table name="alert_def" description="The definition of an alert">
<column name="alert_def_id" type="VARCHAR" size="50" primaryKey="true" required="true" description="Unique identifier for an alert defintion" />
Expand Down
Expand Up @@ -29,8 +29,6 @@
/**
* A class that maps SQL type names to their JDBC type ID found in
* {@link java.sql.Types} and vice versa.
*
* @version $Revision: 463305 $
*/
public abstract class TypeMap
{
Expand Down Expand Up @@ -90,7 +88,7 @@ public abstract class TypeMap
public static final String TIMESTAMP = "TIMESTAMP";

public static final String TIMESTAMPTZ = "TIMESTAMPTZ";

/** The string representation of the {@link java.sql.Types#TINYINT} constant. */
public static final String TINYINT = "TINYINT";
/** The string representation of the {@link java.sql.Types#VARBINARY} constant. */
Expand All @@ -99,7 +97,8 @@ public abstract class TypeMap
public static final String VARCHAR = "VARCHAR";

public static final String SQLXML = "SQLXML";

public static final String GEOMETRY = "GEOMETRY";
public static final String INTERVAL = "INTERVAL";
public static final String NCHAR = "NCHAR";
public static final String NVARCHAR = "NVARCHAR";
public static final String LONGNVARCHAR = "LONGNVARCHAR";
Expand Down
@@ -1,6 +1,7 @@
package org.jumpmind.db.platform.oracle;

import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.TypeMap;
import org.jumpmind.db.sql.DmlStatement;

public class OracleDmlStatement extends DmlStatement {
Expand All @@ -18,6 +19,8 @@ public void appendColumnQuestions(StringBuilder sql, Column[] columns) {
if (columns[i] != null) {
if (columns[i].getTypeCode() == -101) {
sql.append("TO_TIMESTAMP_TZ(?, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM')").append(",");
} else if (columns[i].getJdbcTypeName().toUpperCase().contains(TypeMap.GEOMETRY)) {
sql.append("SYM_WKT2GEOM(?)").append(",");
} else {
sql.append("?").append(",");
}
Expand All @@ -36,6 +39,9 @@ public void appendColumnEquals(StringBuilder sql, Column[] columns, String separ
if (columns[i].getTypeCode() == -101) {
sql.append(quote).append(columns[i].getName()).append(quote)
.append(" = TO_TIMESTAMP_TZ(?, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM')").append(separator);
} else if (columns[i].getJdbcTypeName().toUpperCase().contains(TypeMap.GEOMETRY)) {
sql.append(quote).append(columns[i].getName()).append(quote)
.append(" = ").append("SYM_WKT2GEOM(?)").append(separator);
} else {
sql.append(quote).append(columns[i].getName()).append(quote).append(" = ?").append(separator);
}
Expand Down
Expand Up @@ -36,12 +36,8 @@ public static void setValues(PreparedStatement ps, Object[] args, int[] argTypes
}
}

public static void main(String[] args) {
System.out.println(new byte[] {'0'}.getClass().equals(byte[].class));
}

protected static int verifyArgType(int argType) {
if (argType == -101) {
if (argType == -101 || argType == Types.OTHER) {
return SqlTypeValue.TYPE_UNKNOWN;
} else {
return argType;
Expand Down

0 comments on commit 4a310ae

Please sign in to comment.