Skip to content

Commit

Permalink
support BLOB/CLOB in derby
Browse files Browse the repository at this point in the history
  • Loading branch information
erilong committed Jan 22, 2008
1 parent 019f1fc commit 98401e2
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 16 deletions.
79 changes: 67 additions & 12 deletions symmetric/src/main/java/org/jumpmind/symmetric/db/SqlTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,21 @@ public class SqlTemplate {

public String createInitalLoadSql(Node node, IDbDialect dialect, Trigger trig, Table metaData) {
String sql = sqlTemplates.get(INITIAL_LOAD_SQL_TEMPLATE);

Column[] columns = trig.orderColumnsForTable(metaData);
String columnsText = buildColumnString("t", "t", columns);
sql = replace("columns", columnsText, sql);

sql = replace("tableName", trig.getSourceTableName(), sql);
sql = replace("schemaName", trig.getSourceSchemaName() != null ? trig.getSourceSchemaName() + "." : "", sql);
sql = replace("whereClause", trig.getInitialLoadSelect() == null ? "1=1" : trig.getInitialLoadSelect(), sql);
sql = replace("primaryKeyWhereString", getPrimaryKeyWhereString("t", metaData.getPrimaryKeyColumns()), sql);

// Replace these parameters to give the initiaLoadContition a chance to reference domainNames and domainIds
sql = replace("groupId", node.getNodeGroupId(), sql);
sql = replace("externalId", node.getExternalId(), sql);
sql = replace("nodeId", node.getNodeId(), sql);

Column[] columns = trig.orderColumnsForTable(metaData);
String columnsText = buildColumnString("t", "t", columns);
sql = replace("columns", columnsText, sql);
return sql;
}

Expand All @@ -97,25 +100,31 @@ public String createPurgeSql(Node node, IDbDialect dialect, Trigger trig) {

public String createCsvDataSql(Trigger trig, Table metaData, String whereClause) {
String sql = sqlTemplates.get(INITIAL_LOAD_SQL_TEMPLATE);
sql = replace("tableName", trig.getSourceTableName(), sql);
sql = replace("schemaName", trig.getSourceSchemaName() != null ? trig.getSourceSchemaName() + "." : "", sql);
sql = replace("whereClause", whereClause, sql);

Column[] columns = trig.orderColumnsForTable(metaData);
String columnsText = buildColumnString("t", "t", columns);
sql = replace("columns", columnsText, sql);

sql = replace("tableName", trig.getSourceTableName(), sql);
sql = replace("schemaName", trig.getSourceSchemaName() != null ? trig.getSourceSchemaName() + "." : "", sql);
sql = replace("whereClause", whereClause, sql);
sql = replace("primaryKeyWhereString", getPrimaryKeyWhereString("t", metaData.getPrimaryKeyColumns()), sql);

return sql;
}

public String createCsvPrimaryKeySql(Trigger trig, Table metaData, String whereClause) {
String sql = sqlTemplates.get(INITIAL_LOAD_SQL_TEMPLATE);
sql = replace("tableName", trig.getSourceTableName(), sql);
sql = replace("schemaName", trig.getSourceSchemaName() != null ? trig.getSourceSchemaName() + "." : "", sql);
sql = replace("whereClause", whereClause, sql);

Column[] columns = metaData.getPrimaryKeyColumns();
String columnsText = buildColumnString("t", "t", columns);
sql = replace("columns", columnsText, sql);

sql = replace("tableName", trig.getSourceTableName(), sql);
sql = replace("schemaName", trig.getSourceSchemaName() != null ? trig.getSourceSchemaName() + "." : "", sql);
sql = replace("whereClause", whereClause, sql);
sql = replace("primaryKeyWhereString", getPrimaryKeyWhereString("t", columns), sql);

return sql;
}

Expand Down Expand Up @@ -158,10 +167,7 @@ public String createPostTriggerDDL(IDbDialect dialect, DataEventType dml, Trigge

public String replaceTemplateVariables(IDbDialect dialect, DataEventType dml, Trigger trigger,
TriggerHistory history, String tablePrefix, Table metaData, String defaultSchema, String ddl) {
ddl = replace("tableName", trigger.getSourceTableName().toUpperCase(), ddl);
ddl = replace("targetTableName", trigger.getDefaultTargetTableName().toUpperCase(), ddl);
ddl = replace("schemaName", trigger.getSourceSchemaName() != null ? trigger.getSourceSchemaName().toUpperCase()
+ "." : "", ddl);
ddl = replace("defaultSchema", defaultSchema != null && defaultSchema.length() > 0 ? defaultSchema + "." : "",
ddl);
ddl = replace("triggerName", trigger.getTriggerName(dml, triggerPrefix, dialect.getMaxTriggerNameLength()).toUpperCase(), ddl);
Expand All @@ -186,11 +192,17 @@ public String replaceTemplateVariables(IDbDialect dialect, DataEventType dml, Tr
ddl = replace("columns", columnsText, ddl);
ddl = eval(containsBlobClobColumns(columns), "containsBlobClobColumns", ddl);

// some column templates need tableName and schemaName
ddl = replace("tableName", trigger.getSourceTableName().toUpperCase(), ddl);
ddl = replace("schemaName", trigger.getSourceSchemaName() != null ? trigger.getSourceSchemaName().toUpperCase()
+ "." : "", ddl);

columns = metaData.getPrimaryKeyColumns();
columnsText = buildColumnString(ORIG_TABLE_ALIAS, oldTriggerValue, columns);
ddl = replace("oldKeys", columnsText, ddl);
ddl = replace("oldNewPrimaryKeyJoin", aliasedPrimaryKeyJoin(oldTriggerValue, newTriggerValue, columns), ddl);
ddl = replace("tableNewPrimaryKeyJoin", aliasedPrimaryKeyJoin(ORIG_TABLE_ALIAS, newTriggerValue, columns), ddl);
ddl = replace("primaryKeyWhereString", getPrimaryKeyWhereString(newTriggerValue, columns), ddl);

// replace $(newTriggerValue) and $(oldTriggerValue)
ddl = replace("newTriggerValue", newTriggerValue, ddl);
Expand Down Expand Up @@ -269,6 +281,49 @@ private String aliasedPrimaryKeyJoin(String aliasOne, String aliasTwo, Column[]
return b.toString();
}

// TODO: move to DerbySqlTemplate or change language for use in all DBMSes
private String getPrimaryKeyWhereString(String alias, Column[] columns) {
StringBuilder b = new StringBuilder();
for (Column column : columns) {
b.append("'").append(column.getName()).append("=");
switch (column.getTypeCode()) {
case Types.BIT:
case Types.TINYINT:
case Types.SMALLINT:
case Types.INTEGER:
case Types.BIGINT:
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
case Types.NUMERIC:
case Types.DECIMAL:
case Types.BOOLEAN:
b.append("'").append(triggerConcatCharacter);
b.append("rtrim(char(").append(alias).append(".").append(column.getName()).append("))");
b.append(triggerConcatCharacter).append("'");
break;
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
b.append("'''").append(triggerConcatCharacter);
b.append(alias).append(".").append(column.getName());
b.append(triggerConcatCharacter).append("'''");
break;
case Types.DATE:
case Types.TIMESTAMP:
b.append("{ts '''").append(triggerConcatCharacter);
b.append("rtrim(char(").append(alias).append(".").append(column.getName()).append("))");
b.append(triggerConcatCharacter).append("'''}");
break;
}
if (!column.equals(columns[columns.length - 1])) {
b.append(" and ");
}
}
b.append("'");
return b.toString();
}

private String buildColumnString(String origTableAlias, String tableAlias, Column[] columns) {
String columnsText = "";
for (Column column : columns) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jumpmind.symmetric.db.AbstractDbDialect;
import org.jumpmind.symmetric.db.BinaryEncoding;
import org.jumpmind.symmetric.db.IDbDialect;

public class DerbyDbDialect extends AbstractDbDialect implements IDbDialect {
Expand Down Expand Up @@ -56,11 +57,15 @@ public void removeTrigger(String schemaName, String triggerName, String tableNam
}

public boolean isBlobSyncSupported() {
return false;
return true;
}

public boolean isClobSyncSupported() {
return false;
return true;
}

public BinaryEncoding getBinaryEncoding() {
return BinaryEncoding.BASE64;
}

public void disableSyncTriggers() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
package org.jumpmind.symmetric.db.derby;

import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Hashtable;

import org.apache.commons.codec.binary.Base64;
import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
import org.apache.derby.impl.jdbc.EmbedConnection;

public class DerbyFunctions {

private static final String CURRENT_CONNECTION_URL = "jdbc:default:connection";

private static final int MAX_STRING_LENGTH = 32672;

// Base64 will output roughly 1.37% size of input
private static final int MAX_BINARY_LENGTH = 23700;

private static Hashtable<String, Boolean> syncDisabledTable = new Hashtable<String, Boolean>();

public static String getTransactionId() throws SQLException {
Expand Down Expand Up @@ -70,6 +79,40 @@ public static void insertData(String schemaName, String prefixName, String table
}
}

public static String blobToString(String columnName, String tableName, String whereClause) throws SQLException {
Connection conn = DriverManager.getConnection(CURRENT_CONNECTION_URL);
String sql = "select " + columnName + " from " + tableName + " where " + whereClause;
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
String str = null;
if (rs.next()) {
Blob blob = rs.getBlob(1);
if (blob != null && blob.length() > 0) {
str = new String(Base64.encodeBase64(blob.getBytes(1, MAX_BINARY_LENGTH)));
}
}
ps.close();
conn.close();
return str == null ? "" : "\"" + str + "\"";
}

public static String clobToString(String columnName, String tableName, String whereClause) throws SQLException {
Connection conn = DriverManager.getConnection(CURRENT_CONNECTION_URL);
String sql = "select " + columnName + " from " + tableName + " where " + whereClause;
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
String str = null;
if (rs.next()) {
Clob clob = rs.getClob(1);
if (clob != null && clob.length() > 0) {
str = clob.getSubString(1, MAX_STRING_LENGTH);
}
}
ps.close();
conn.close();
return str == null ? "" : "\"" + str + "\"";
}

private static LanguageConnectionContext getLanguageConnection() throws SQLException {
EmbedConnection conn = (EmbedConnection) DriverManager.getConnection(CURRENT_CONNECTION_URL);
return conn.getLanguageConnection();
Expand Down
24 changes: 22 additions & 2 deletions symmetric/src/main/resources/dialects/derby.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,26 @@
]]>
</value>
</entry>
<entry key="FN_SYM_CLOB_TO_STRING">
<value>
<![CDATA[
CREATE FUNCTION fn_sym_clob_to_string(columnName varchar(50),
tableName varchar(50), whereClause varchar(8000)) RETURNS
varchar(32672) PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME
'org.jumpmind.symmetric.db.derby.DerbyFunctions.clobToString'
]]>
</value>
</entry>
<entry key="FN_SYM_BLOB_TO_STRING">
<value>
<![CDATA[
CREATE FUNCTION fn_sym_blob_to_string(columnName varchar(50),
tableName varchar(50), whereClause varchar(8000)) RETURNS
varchar(32672) PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME
'org.jumpmind.symmetric.db.derby.DerbyFunctions.blobToString'
]]>
</value>
</entry>
<entry key="PROC_SYM_INSERT_DATA">
<value>
<![CDATA[
Expand All @@ -78,12 +98,12 @@
</property>
<property name="clobColumnTemplate">
<value>
<![CDATA['unsupported'||','||]]>
<![CDATA[fn_sym_clob_to_string('$(columnName)', '$(schemaName)$(tableName)', $(primaryKeyWhereString) )||','||]]>
</value>
</property>
<property name="blobColumnTemplate">
<value>
<![CDATA['unsupported'||','||]]>
<![CDATA[fn_sym_blob_to_string('$(columnName)', '$(schemaName)$(tableName)', $(primaryKeyWhereString) )||','||]]>
</value>
</property>
<property name="numberColumnTemplate">
Expand Down

0 comments on commit 98401e2

Please sign in to comment.