package com.zendesk.maxwell;
import com.zendesk.maxwell.row.RowMap;
import org.junit.Test;
import java.sql.Timestamp;
import java.util.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
public class BootstrapIntegrationTest extends MaxwellTestWithIsolatedServer {
@Test
public void testSingleRowBootstrap() throws Exception {
runJSON("json/bootstrap-single-row");
}
@Test
public void testMultipleRowBootstrap() throws Exception {
runJSON("json/bootstrap-multiple-row");
}
@Test
public void testMultipleRowBootstrapWithWhereclause() throws Exception {
runJSON("json/bootstrap-multiple-row-with-whereclause");
}
@Test
public void testNoPkTableBootstrap() throws Exception {
runJSON("json/bootstrap-no-pk");
}
@Test
public void testMultipleTablesBootstrap() throws Exception {
runJSON("json/bootstrap-multiple-tables");
}
@Test
public void testBootstrapIsWhitelisted() throws Exception {
MaxwellFilter filter = new MaxwellFilter();
filter.includeDatabase("shard_1");
runJSON("json/bootstrap-whitelist", filter);
}
@Test
public void testBootstrapNullValues() throws Exception {
runJSON("json/bootstrap-null-values");
}
@Test
public void testBool() throws Exception {
testColumnType("bool", "0", 0);
testColumnType("bool", "1", 1);
}
@Test
public void testBoolean() throws Exception {
testColumnType("boolean", "0", 0);
testColumnType("boolean", "1", 1);
}
@Test
public void testTinyInt() throws Exception {
testColumnType("tinyint", "-128", -128);
testColumnType("tinyint", "127", 127);
testColumnType("tinyint unsigned", "0", 0);
testColumnType("tinyint unsigned", "255", 255);
}
@Test
public void testSmallInt() throws Exception {
testColumnType("smallint", "-32768", -32768);
testColumnType("smallint", "32767", 32767);
testColumnType("smallint unsigned", "0", 0);
testColumnType("smallint unsigned", "65535", 65535);
}
@Test
public void testMediumInt() throws Exception {
testColumnType("mediumint", "-8388608", -8388608);
testColumnType("mediumint", "8388607", 8388607);
testColumnType("mediumint unsigned", "0", 0);
testColumnType("mediumint unsigned", "16777215", 16777215);
}
@Test
public void testInt() throws Exception {
testColumnType("int", "-2147483648", -2147483648);
testColumnType("int", "2147483647", 2147483647);
testColumnType("int unsigned", "0", 0);
// throws MySQLDataException
//testColumnType("int unsigned", "4294967295", "4294967295");
}
@Test
public void testBigInt() throws Exception {
testColumnType("bigint", "-9223372036854775808", -9223372036854775808L);
testColumnType("bigint", "9223372036854775807", 9223372036854775807L);
testColumnType("bigint unsigned", "0", 0);
// throws MySQLDataException
//testColumnType("bigint unsigned", "18446744073709551615", "18446744073709551615");
}
@Test
public void testStringTypes( ) throws Exception {
String epoch = String.valueOf(new Timestamp(0)); // timezone dependent
testColumnType("datetime", "'1000-01-01 00:00:00'","1000-01-01 00:00:00", null);
testColumnType("tinytext", "'hello'", "hello");
testColumnType("text", "'hello'", "hello");
testColumnType("mediumtext","'hello'", "hello");
testColumnType("longtext","'hello'", "hello");
testColumnType("varchar(10)","'hello'", "hello");
testColumnType("char", "'h'", "h");
testColumnType("date", "'2015-11-07'","2015-11-07");
testColumnType("datetime", "'2015-11-07 01:02:03'","2015-11-07 01:02:03");
if ( !server.getVersion().equals("5.7") ) {
testColumnType("date", "'0000-00-00'",null);
testColumnType("datetime", "'0000-00-00 00:00:00'", null);
testColumnType("timestamp", "'0000-00-00 00:00:00'","" + epoch.substring(0, epoch.length() - 2) + "", null);
}
testColumnType("datetime", "'1000-01-01 00:00:00'","1000-01-01 00:00:00");
testColumnType("timestamp", "'2015-11-07 01:02:03'","2015-11-07 01:02:03");
testColumnType("enum('a', 'b')","'a'", "a");
testColumnType("bit(8)","b'01010101'", 85);
testColumnType("bit(8)","b'1'", 1);
}
@Test
public void testSubsecondTypes() throws Exception {
if ( server.getVersion().equals("5.6") ) {
testColumnType("timestamp(6)", "'2015-11-07 01:02:03.333444'","2015-11-07 01:02:03.333444");
testColumnType("timestamp(6)", "'2015-11-07 01:02:03.123'","2015-11-07 01:02:03.123000");
testColumnType("timestamp(6)", "'2015-11-07 01:02:03.0'","2015-11-07 01:02:03.000000");
testColumnType("timestamp(3)", "'2015-11-07 01:02:03.123456'","2015-11-07 01:02:03.123");
testColumnType("timestamp(3)", "'2015-11-07 01:02:03.123'","2015-11-07 01:02:03.123");
testColumnType("timestamp(3)", "'2015-11-07 01:02:03.1'","2015-11-07 01:02:03.100");
testColumnType("timestamp(3)", "'2015-11-07 01:02:03.0'","2015-11-07 01:02:03.000");
testColumnType("datetime(6)", "'2015-11-07 01:02:03.123456'","2015-11-07 01:02:03.123456");
testColumnType("datetime(6)", "'2015-11-07 01:02:03.123'","2015-11-07 01:02:03.123000");
testColumnType("datetime(3)", "'2015-11-07 01:02:03.123456'","2015-11-07 01:02:03.123");
testColumnType("datetime(3)", "'2015-11-07 01:02:03.123'","2015-11-07 01:02:03.123");
testColumnType("time(3)", "'01:02:03.123456'","01:02:03.123");
testColumnType("time(6)", "'01:02:03.123456'","01:02:03.123456");
testColumnType("time(3)", "'01:02:03.123'","01:02:03.123");
}
}
@Test
public void testSetType() throws Exception {
ArrayList<String> setValue = new ArrayList<>(2);
setValue.add("a");
setValue.add("b");
testColumnType("set('a', 'b')","'a,b'", setValue);
}
@Test
public void testBinaryTypes( ) throws Exception {
testColumnType("tinyblob", "x'0A0B0C0D0E0F'", "CgsMDQ4P");
testColumnType("blob", "x'0A0B0C0D0E0F'", "CgsMDQ4P");
testColumnType("mediumblob","x'0A0B0C0D0E0F'", "CgsMDQ4P");
testColumnType("longblob","x'0A0B0C0D0E0F'", "CgsMDQ4P");
testColumnType("binary(6)","x'0A0B0C0D0E0F'", "CgsMDQ4P");
testColumnType("binary(6)","x'0A0B0C0D0E0F'", "CgsMDQ4P");
// Unlike MySQL, the Maxwell replicator does not pad short binary values, but the Maxwell bootstrapper does!
testColumnType("binary(10)","x'0A0B0C0D0E0F'", "CgsMDQ4P", "CgsMDQ4PAAAAAA==");
testColumnType("varbinary(10)","x'0A0B0C0D0E0F'", "CgsMDQ4P");
}
@Test
public void testOtherNumericTypes() throws Exception {
testColumnType("real", "3.14159", 3.14159);
testColumnType("float","3.14159", 3.14159);
testColumnType("double","3.14159", 3.14159);
testColumnType("numeric(20,10)","3.14159", 3.1415900000);
testColumnType("decimal(20,10)","3.14159", 3.1415900000);
testColumnType("year","2007", 2007);
}
private void testColumnType(String sqlType, String sqlValue, Object expectedJsonValue) throws Exception {
testColumnType(sqlType, sqlValue, expectedJsonValue, expectedJsonValue);
}
private void testColumnType(String sqlType, String sqlValue, Object expectedNormalJsonValue, Object expectedBootstrappedJsonValue) throws Exception {
String input[] = {
"DROP TABLE IF EXISTS shard_1.column_test",
String.format("CREATE TABLE IF NOT EXISTS shard_1.column_test (id int unsigned auto_increment NOT NULL primary key, col %s)", sqlType),
String.format("INSERT INTO shard_1.column_test SET col = %s", sqlValue),
"INSERT INTO maxwell.bootstrap set database_name = 'shard_1', table_name = 'column_test'"
};
List<RowMap> rows = getRowsForSQL(input);
boolean foundNormalRow = false;
for ( RowMap r : rows ) {
String json = r.toJSON();
Map<String, Object> data, output = MaxwellTestJSON.parseJSON(r.toJSON());
if ( output.get("table").equals("column_test") && output.get("type").equals("insert") ) {
data = (Map<String, Object>) output.get("data");
if ( !foundNormalRow ) {
foundNormalRow = true;
assertThat(data.get("col"), is(expectedNormalJsonValue));
} else {
assertThat(data.get("col"), is(expectedBootstrappedJsonValue));
}
}
}
}
}