package com.zendesk.maxwell.schema.columndef; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import com.google.code.or.common.util.MySQLConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class StringColumnDef extends ColumnDef { public String charset; static final Logger LOGGER = LoggerFactory.getLogger(StringColumnDef.class); public StringColumnDef(String name, String type, int pos, String charset) { super(name, type, pos); this.charset = charset; } public String getCharset() { return charset; } public void setCharset(String charset) { this.charset = charset; } public void setDefaultCharset(String e) { if ( this.charset == null ) this.charset = e; } @Override public boolean matchesMysqlType(int type) { return type == MySQLConstants.TYPE_BLOB || type == MySQLConstants.TYPE_VARCHAR || type == MySQLConstants.TYPE_STRING; } @Override public String toSQL(Object value) { byte[] b = (byte[]) value; if ( charset.equals("utf8") || charset.equals("utf8mb4")) { return quoteString(new String(b)); } else { return "x'" + Hex.encodeHexString( b ) + "'"; } } // this could obviously be more complete. private Charset charsetForCharset() { switch(charset.toLowerCase()) { case "utf8": case "utf8mb4": return Charset.forName("UTF-8"); case "latin1": case "ascii": return Charset.forName("ISO-8859-1"); case "ucs2": return Charset.forName("UTF-16"); default: try { return Charset.forName(charset.toLowerCase()); } catch ( java.nio.charset.UnsupportedCharsetException e ) { throw new RuntimeException("error: unhandled character set '" + charset + "'"); } } } @Override public Object asJSON(Object value) { if ( value instanceof String ) { return value; } byte[] b = (byte[])value; if ( charset.equals("binary") ) { return Base64.encodeBase64String(b); } else { return new String(b, charsetForCharset()); } } private String quoteString(String s) { String escaped = s.replaceAll("'", "''"); escaped = escaped.replaceAll("\n", "\\\\n"); escaped = escaped.replaceAll("\r", "\\\\r"); return "'" + escaped + "'"; } }