package com.zendesk.maxwell.schema.columndef;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import com.zendesk.maxwell.TestWithNameLogging;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.code.or.common.util.MySQLConstants;
public class ColumnDefTest extends TestWithNameLogging {
private ColumnDef build(String type, boolean signed) {
return ColumnDef.build("bar", "", type, 1, signed, null, null);
}
private ColumnDef build(String type, boolean signed, Long columnLength) {
return ColumnDef.build("bar", "", type, 1, signed, null, columnLength);
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testTinyInt() {
ColumnDef d = build("tinyint", true);
assertThat(d, instanceOf(IntColumnDef.class));
assertThat(d.toSQL(Integer.valueOf(5)), is("5"));
assertThat(d.toSQL(Integer.valueOf(-5)), is("-5"));
d = build("tinyint", false);
assertThat(d.toSQL(Integer.valueOf(10)), is("10"));
assertThat(d.toSQL(Integer.valueOf(-10)), is("246"));
}
@Test
public void testShortInt() {
ColumnDef d = build("smallint", true);
assertThat(d, instanceOf(IntColumnDef.class));
assertThat(d.toSQL(Integer.valueOf(5)), is("5"));
assertThat(d.toSQL(Integer.valueOf(-5)), is("-5"));
d = build("smallint", false);
assertThat(d.toSQL(Integer.valueOf(-10)), is("65526"));
}
@Test
public void testMediumInt() {
ColumnDef d = build("mediumint", true);
assertThat(d, instanceOf(IntColumnDef.class));
assertThat(d.toSQL(Integer.valueOf(5)), is("5"));
assertThat(d.toSQL(Integer.valueOf(-5)), is("-5"));
d = build("mediumint", false);
assertThat(d.toSQL(Integer.valueOf(-10)), is("16777206"));
}
@Test
public void testInt() {
ColumnDef d = build("int", true);
assertThat(d, instanceOf(IntColumnDef.class));
assertThat(d.toSQL(Integer.valueOf(5)), is("5"));
assertThat(d.toSQL(Integer.valueOf(-5)), is("-5"));
d = build("int", false);
assertThat(d.toSQL(Integer.valueOf(-10)), is("4294967286"));
}
@Test
public void testBigInt() {
ColumnDef d = build("bigint", true);
assertThat(d, instanceOf(BigIntColumnDef.class));
assertThat(d.toSQL(Long.valueOf(5)), is("5"));
assertThat(d.toSQL(Long.valueOf(-5)), is("-5"));
d = build("bigint", false);
assertThat(d.toSQL(Long.valueOf(-10)), is("18446744073709551606"));
}
@Test
public void testUTF8String() {
ColumnDef d = ColumnDef.build("bar", "utf8", "varchar", 1, false, null, null);
assertThat(d, instanceOf(StringColumnDef.class));
byte input[] = "He∆˚ß∆".getBytes();
assertThat(d.toSQL(input), is("'He∆˚ß∆'"));
}
@Test
public void TestUTF8MB4String() {
String utf8_4 = "😁";
ColumnDef d = ColumnDef.build("bar", "utf8mb4", "varchar", 1, false, null, null);
byte input[] = utf8_4.getBytes();
assertThat(d.toSQL(input), is("'😁'"));
}
@Test
public void TestAsciiString() {
byte input[] = new byte[4];
input[0] = Byte.valueOf((byte) 126);
input[1] = Byte.valueOf((byte) 126);
input[2] = Byte.valueOf((byte) 126);
input[3] = Byte.valueOf((byte) 126);
ColumnDef d = ColumnDef.build("bar", "ascii", "varchar", 1, false, null, null);
assertThat((String) d.asJSON(input), is("~~~~"));
}
@Test
public void TestStringAsJSON() {
byte input[] = new byte[4];
input[0] = Byte.valueOf((byte) 169);
input[1] = Byte.valueOf((byte) 169);
input[2] = Byte.valueOf((byte) 169);
input[3] = Byte.valueOf((byte) 169);
ColumnDef d = ColumnDef.build("bar", "latin1", "varchar", 1, false, null, null);
assertThat((String) d.asJSON(input), is("©©©©"));
}
@Test
public void TestFloat() {
ColumnDef d = build("float", true);
assertThat(d, instanceOf(FloatColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_FLOAT));
assertFalse(d.matchesMysqlType(MySQLConstants.TYPE_DOUBLE));
assertThat(d.toSQL(Float.valueOf(1.2f)), is("1.2"));
}
@Test
public void TestDouble() {
ColumnDef d = build("double", true);
assertThat(d, instanceOf(FloatColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_DOUBLE));
assertFalse(d.matchesMysqlType(MySQLConstants.TYPE_FLOAT));
String maxDouble = Double.valueOf(Double.MAX_VALUE).toString();
assertThat(d.toSQL(Double.valueOf(Double.MAX_VALUE)), is(maxDouble));
}
@Test
public void TestTime() throws ParseException {
ColumnDef d = build("time", true);
assertThat(d, instanceOf(TimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_TIME));
Timestamp t = new Timestamp(307653559000L - TimeZone.getDefault().getOffset(307653559000L));
assertThat(d.toSQL(t), is("'19:19:19'"));
}
@Test
public void TestTimeWithMillisecTimestamp() throws ParseException {
ColumnDef d = build("time", true, 3L);
assertThat(d, instanceOf(TimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_TIME));
Timestamp t = new Timestamp(307653559000L - TimeZone.getDefault().getOffset(307653559000L));
t.setNanos(0);
assertThat(d.toSQL(t), is("'19:19:19.000'"));
t.setNanos(123000);
assertThat(d.toSQL(t), is("'19:19:19.000'"));
t.setNanos(123456789);
assertThat(d.toSQL(t), is("'19:19:19.123'"));
}
@Test
public void TestTimeWithMicrosecTimestamp() throws ParseException {
ColumnDef d = build("time", true, 6L);
assertThat(d, instanceOf(TimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_TIME));
Timestamp t = new Timestamp(307653559000L - TimeZone.getDefault().getOffset(307653559000L));
t.setNanos(0);
assertThat(d.toSQL(t), is("'19:19:19.000000'"));
t.setNanos(123456789);
assertThat(d.toSQL(t), is("'19:19:19.123456'"));
t.setNanos(123000);
assertThat(d.toSQL(t), is("'19:19:19.000123'"));
}
@Test
public void TestDate() {
ColumnDef d = build("date", true);
assertThat(d, instanceOf(DateColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_DATE));
Date date = new GregorianCalendar(1979, 10, 1).getTime();
assertThat(d.toSQL(date), is("'1979-11-01'"));
}
@Test
public void TestDateTime() throws ParseException {
ColumnDef d = build("datetime", true);
assertThat(d, instanceOf(DateTimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_DATETIME));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = simpleDateFormat.parse("1979-10-01 19:19:19");
assertThat(d.toSQL(date), is("'1979-10-01 19:19:19'"));
}
@Test
public void TestDateTimeWithTimestamp() throws ParseException {
ColumnDef d = build("datetime", true);
assertThat(d, instanceOf(DateTimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_DATETIME));
Timestamp t = Timestamp.valueOf("1979-10-01 19:19:19");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19'"));
}
@Test
public void TestDateTimeWithMillisecprecision() throws ParseException {
ColumnDef d = build("datetime", true, 3L);
assertThat(d, instanceOf(DateTimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_DATETIME));
Timestamp t = Timestamp.valueOf("1979-10-01 19:19:19.123");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.123'"));
t = Timestamp.valueOf("1979-10-01 19:19:19");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.000'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.001");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.001'"));
}
@Test
public void TestDateTimeWithMicroPrecision() throws ParseException {
ColumnDef d = build("datetime", true, 6L);
assertThat(d, instanceOf(DateTimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_DATETIME));
Timestamp t = Timestamp.valueOf("1979-10-01 19:19:19.001000");
org.junit.Assert.assertEquals(1000000, t.getNanos());
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.001000'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.000001");
org.junit.Assert.assertEquals(1000, t.getNanos());
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.000001'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.345678");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.345678'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.100000");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.100000'"));
}
@Test
public void TestTimestamp() throws ParseException {
ColumnDef d = build("timestamp", true);
assertThat(d, instanceOf(DateTimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_TIMESTAMP));
Timestamp t = Timestamp.valueOf("1979-10-01 19:19:19");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19'"));
}
@Test
public void TestTimestampWithMilliSecPrecision() throws ParseException {
ColumnDef d = build("timestamp", true, 3L);
assertThat(d, instanceOf(DateTimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_TIMESTAMP));
Timestamp t = Timestamp.valueOf("1979-10-01 19:19:19.123456000");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.123'"));
t = Timestamp.valueOf("1979-10-01 19:19:19");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.000'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.000");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.000'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.001");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.001'"));
}
@Test
public void TestTimestampWithMicroSecPrecision() throws ParseException {
ColumnDef d = build("timestamp", true, 6L);
assertThat(d, instanceOf(DateTimeColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_TIMESTAMP));
Timestamp t = Timestamp.valueOf("1979-10-01 19:19:19.123456000");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.123456'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.000123");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.000123'"));
t = Timestamp.valueOf("1979-10-01 19:19:19.000001");
assertThat(d.toSQL(t), is("'1979-10-01 19:19:19.000001'"));
}
@Test
public void TestBit() {
ColumnDef d = build("bit", true);
assertThat(d, instanceOf(BitColumnDef.class));
assertTrue(d.matchesMysqlType(MySQLConstants.TYPE_BIT));
byte[] b = new byte[]{0x1};
assertThat(d.toSQL(b), is("1"));
b = new byte[]{0x0};
assertThat(d.toSQL(b), is("0"));
Boolean bO = Boolean.TRUE;
assertThat(d.toSQL(bO), is("1"));
bO = Boolean.FALSE;
assertThat(d.toSQL(bO), is("0"));
}
}