DBZ-252 Rebase to master

This commit is contained in:
Jiri Pechanec 2018-06-12 14:57:15 +02:00 committed by Gunnar Morling
parent 5022933581
commit 9580c8c290
18 changed files with 506 additions and 361 deletions

View File

@ -73,6 +73,7 @@ public Object convert(Column column, String value) {
case Types.FLOAT:
case Types.DOUBLE:
case Types.REAL:
return convertToDouble(value);
case Types.BIGINT:
return convertToBigInt(value);

View File

@ -5,6 +5,7 @@
*/
package io.debezium.connector.mysql;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
@ -98,18 +99,6 @@ public MySqlSchema(Configuration config, String serverName, Predicate<String> gt
this.topicSelector = topicSelector;
this.tableIdCaseInsensitive = tableIdCaseInsensitive;
String ddlParsingModeStr = config.getString(MySqlConnectorConfig.DDL_PARSER_MODE);
DdlParsingMode parsingMode = DdlParsingMode.parse(ddlParsingModeStr, MySqlConnectorConfig.DDL_PARSER_MODE.defaultValueAsString());
try {
this.ddlParser = parsingMode.getParserClass().newInstance();
this.ddlChanges = this.ddlParser.getDdlChanges();
}
catch (InstantiationException | IllegalAccessException e) {
// ddl parser constructors are not throwing any exceptions, so this should never happen
throw new IllegalArgumentException("Unable to create new instance for ddl parser class " + parsingMode.getParserClass().getCanonicalName());
}
// Use MySQL-specific converters and schemas for values ...
String timePrecisionModeStr = config.getString(MySqlConnectorConfig.TIME_PRECISION_MODE);
TemporalPrecisionMode timePrecisionMode = TemporalPrecisionMode.parse(timePrecisionModeStr);
@ -122,9 +111,17 @@ public MySqlSchema(Configuration config, String serverName, Predicate<String> gt
MySqlValueConverters valueConverters = new MySqlValueConverters(decimalMode, timePrecisionMode, bigIntUnsignedMode);
this.schemaBuilder = new TableSchemaBuilder(valueConverters, schemaNameAdjuster, SourceInfo.SCHEMA);
this.ddlParser = new MySqlDdlParser(false, valueConverters);
this.ddlChanges = new DdlChanges(this.ddlParser.terminator());
this.ddlParser.addListener(ddlChanges);
String ddlParsingModeStr = config.getString(MySqlConnectorConfig.DDL_PARSER_MODE);
DdlParsingMode parsingMode = DdlParsingMode.parse(ddlParsingModeStr, MySqlConnectorConfig.DDL_PARSER_MODE.defaultValueAsString());
try {
this.ddlParser = parsingMode.getParserClass().getConstructor(MySqlValueConverters.class).newInstance(valueConverters);
this.ddlChanges = this.ddlParser.getDdlChanges();
}
catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// ddl parser constructors are not throwing any exceptions, so this should never happen
throw new IllegalArgumentException("Unable to create new instance for ddl parser class " + parsingMode.getParserClass().getCanonicalName());
}
// Set up the server name and schema prefix ...
if (serverName != null) serverName = serverName.trim();

View File

@ -11,6 +11,7 @@
import io.debezium.antlr.DataTypeResolver;
import io.debezium.antlr.DataTypeResolver.DataTypeEntry;
import io.debezium.connector.mysql.MySqlSystemVariables;
import io.debezium.connector.mysql.MySqlValueConverters;
import io.debezium.connector.mysql.antlr.listener.MySqlAntlrDdlParserListener;
import io.debezium.ddl.parser.mysql.generated.MySqlLexer;
import io.debezium.ddl.parser.mysql.generated.MySqlParser;
@ -40,18 +41,24 @@
public class MySqlAntlrDdlParser extends AntlrDdlParser<MySqlLexer, MySqlParser> {
private final ConcurrentMap<String, String> charsetNameForDatabase = new ConcurrentHashMap<>();
private final MySqlValueConverters converters;
public MySqlAntlrDdlParser() {
this(true);
}
public MySqlAntlrDdlParser(boolean throwErrorsFromTreeWalk) {
this(throwErrorsFromTreeWalk, false);
public MySqlAntlrDdlParser(MySqlValueConverters converters) {
this(true, false, converters);
}
public MySqlAntlrDdlParser(boolean throwErrorsFromTreeWalk, boolean includeViews) {
public MySqlAntlrDdlParser(boolean throwErrorsFromTreeWalk) {
this(throwErrorsFromTreeWalk, false, null);
}
public MySqlAntlrDdlParser(boolean throwErrorsFromTreeWalk, boolean includeViews, MySqlValueConverters converters) {
super(throwErrorsFromTreeWalk, includeViews);
systemVariables = new MySqlSystemVariables();
this.converters = converters;
}
@Override
@ -291,4 +298,8 @@ public static List<String> parseSetAndEnumOptions(String typeExpression) {
return options;
}
public MySqlValueConverters getConverters() {
return converters;
}
}

View File

@ -70,7 +70,7 @@ public void enterAlterByAddColumn(MySqlParser.AlterByAddColumnContext ctx) {
parserCtx.runIfNotNull(() -> {
String columnName = parserCtx.parseName(ctx.uid(0));
ColumnEditor columnEditor = Column.editor().name(columnName);
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parserCtx.dataTypeResolver());
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parserCtx.dataTypeResolver(), parserCtx.getConverters());
listeners.add(columnDefinitionListener);
}, tableEditor);
super.exitAlterByAddColumn(ctx);
@ -103,7 +103,7 @@ public void enterAlterByAddColumns(MySqlParser.AlterByAddColumnsContext ctx) {
String columnName = parserCtx.parseName(uidContext);
columnEditors.add(Column.editor().name(columnName));
}
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditors.get(0), parserCtx.dataTypeResolver());
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditors.get(0), parserCtx.dataTypeResolver(), parserCtx.getConverters());
listeners.add(columnDefinitionListener);
}, tableEditor);
super.enterAlterByAddColumns(ctx);
@ -143,7 +143,7 @@ public void enterAlterByChangeColumn(MySqlParser.AlterByChangeColumnContext ctx)
String oldColumnName = parserCtx.parseName(ctx.oldColumn);
Column existingColumn = tableEditor.columnWithName(oldColumnName);
if (existingColumn != null) {
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, existingColumn.edit(), parserCtx.dataTypeResolver());
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, existingColumn.edit(), parserCtx.dataTypeResolver(), parserCtx.getConverters());
listeners.add(columnDefinitionListener);
}
else {
@ -178,7 +178,7 @@ public void enterAlterByModifyColumn(MySqlParser.AlterByModifyColumnContext ctx)
String columnName = parserCtx.parseName(ctx.uid(0));
Column column = tableEditor.columnWithName(columnName);
if (column != null) {
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, column.edit(), parserCtx.dataTypeResolver());
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, column.edit(), parserCtx.dataTypeResolver(), parserCtx.getConverters());
listeners.add(columnDefinitionListener);
}
else {

View File

@ -6,18 +6,26 @@
package io.debezium.connector.mysql.antlr.listener;
import io.debezium.antlr.DataTypeResolver;
import io.debezium.ddl.parser.mysql.generated.MySqlParser;
import io.debezium.ddl.parser.mysql.generated.MySqlParserBaseListener;
import io.debezium.relational.Column;
import io.debezium.relational.ColumnEditor;
import io.debezium.relational.TableEditor;
import io.debezium.relational.ddl.DataType;
import static io.debezium.antlr.AntlrDdlParser.getText;
import java.sql.Types;
import java.util.List;
import static io.debezium.antlr.AntlrDdlParser.getText;
import org.apache.kafka.connect.data.Field;
import org.apache.kafka.connect.data.Schema;
import org.apache.kafka.connect.data.SchemaBuilder;
import io.debezium.antlr.DataTypeResolver;
import io.debezium.connector.mysql.MySqlDefaultValuePreConverter;
import io.debezium.connector.mysql.MySqlValueConverters;
import io.debezium.ddl.parser.mysql.generated.MySqlParser;
import io.debezium.ddl.parser.mysql.generated.MySqlParser.DefaultValueContext;
import io.debezium.ddl.parser.mysql.generated.MySqlParserBaseListener;
import io.debezium.relational.Column;
import io.debezium.relational.ColumnEditor;
import io.debezium.relational.TableEditor;
import io.debezium.relational.ValueConverter;
import io.debezium.relational.ddl.DataType;
/**
* Parser listeners that is parsing column definition part of MySQL statements.
@ -30,10 +38,14 @@ public class ColumnDefinitionParserListener extends MySqlParserBaseListener {
private final TableEditor tableEditor;
private ColumnEditor columnEditor;
public ColumnDefinitionParserListener(TableEditor tableEditor, ColumnEditor columnEditor, DataTypeResolver dataTypeResolver) {
private final MySqlValueConverters converters;
private final MySqlDefaultValuePreConverter defaultValuePreConverter = new MySqlDefaultValuePreConverter();
public ColumnDefinitionParserListener(TableEditor tableEditor, ColumnEditor columnEditor, DataTypeResolver dataTypeResolver, MySqlValueConverters converters) {
this.tableEditor = tableEditor;
this.columnEditor = columnEditor;
this.dataTypeResolver = dataTypeResolver;
this.converters = converters;
}
public void setColumnEditor(ColumnEditor columnEditor) {
@ -80,6 +92,44 @@ public void enterNullNotnull(MySqlParser.NullNotnullContext ctx) {
super.enterNullNotnull(ctx);
}
@Override
public void enterDefaultValue(DefaultValueContext ctx) {
String sign = "";
if (ctx.NULL_LITERAL() != null) {
return;
}
if (ctx.unaryOperator() != null) {
sign = ctx.unaryOperator().getText();
}
if (ctx.constant() != null) {
if (ctx.constant().stringLiteral() != null) {
columnEditor.defaultValue(sign + unquote(ctx.constant().stringLiteral().getText()));
}
else if (ctx.constant().decimalLiteral() != null) {
columnEditor.defaultValue(sign + ctx.constant().decimalLiteral().getText());
}
else if (ctx.constant().BIT_STRING() != null) {
columnEditor.defaultValue(unquoteBinary(ctx.constant().BIT_STRING().getText()));
}
else if (ctx.constant().booleanLiteral() != null) {
columnEditor.defaultValue(ctx.constant().booleanLiteral().getText());
}
else if (ctx.constant().REAL_LITERAL() != null) {
columnEditor.defaultValue(ctx.constant().REAL_LITERAL().getText());
}
}
else if (ctx.timeDefinition() != null) {
if (ctx.timeDefinition().CURRENT_TIMESTAMP() != null || ctx.timeDefinition().NOW() != null) {
columnEditor.defaultValue("1970-01-01 00:00:00");
}
else {
columnEditor.defaultValue(ctx.timeDefinition().getText());
}
}
convertDefaultValueToSchemaType(columnEditor);
super.enterDefaultValue(ctx);
}
@Override
public void enterAutoIncrementColumnConstraint(MySqlParser.AutoIncrementColumnConstraintContext ctx) {
columnEditor.autoIncremented(true);
@ -191,4 +241,35 @@ else if (dataTypeContext instanceof MySqlParser.CollectionDataTypeContext) {
columnEditor.charsetName(charsetName);
}
}
private void convertDefaultValueToSchemaType(ColumnEditor columnEditor) {
final Column column = columnEditor.create();
// if converters is not null and the default value is not null, we need to convert default value
if (converters != null && columnEditor.defaultValue() != null) {
Object defaultValue = columnEditor.defaultValue();
final SchemaBuilder schemaBuilder = converters.schemaBuilder(column);
if (schemaBuilder == null) {
return;
}
final Schema schema = schemaBuilder.build();
//In order to get the valueConverter for this column, we have to create a field;
//The index value -1 in the field will never used when converting default value;
//So we can set any number here;
final Field field = new Field(column.name(), -1, schema);
final ValueConverter valueConverter = converters.converter(column, field);
if (defaultValue instanceof String) {
defaultValue = defaultValuePreConverter.convert(column, (String)defaultValue);
}
defaultValue = valueConverter.convert(defaultValue);
columnEditor.defaultValue(defaultValue);
}
}
private String unquote(String stringLiteral) {
return stringLiteral.substring(1, stringLiteral.length() - 1);
}
private String unquoteBinary(String stringLiteral) {
return stringLiteral.substring(2, stringLiteral.length() - 1);
}
}

View File

@ -77,7 +77,7 @@ public void enterColumnDeclaration(MySqlParser.ColumnDeclarationContext ctx) {
String columnName = parserCtx.parseName(ctx.uid());
ColumnEditor columnEditor = Column.editor().name(columnName);
if (columnDefinitionListener == null) {
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parserCtx.dataTypeResolver());
columnDefinitionListener = new ColumnDefinitionParserListener(tableEditor, columnEditor, parserCtx.dataTypeResolver(), parserCtx.getConverters());
listeners.add(columnDefinitionListener);
} else {
columnDefinitionListener.setColumnEditor(columnEditor);

View File

@ -0,0 +1,320 @@
/*
* Copyright Debezium Authors.
*
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package io.debezium.connector.mysql;
import static org.fest.assertions.Assertions.assertThat;
import java.math.BigDecimal;
import java.util.function.Function;
import org.junit.Before;
import org.junit.Test;
import io.debezium.jdbc.JdbcValueConverters;
import io.debezium.jdbc.TemporalPrecisionMode;
import io.debezium.relational.Table;
import io.debezium.relational.TableId;
import io.debezium.relational.Tables;
import io.debezium.relational.ddl.AbstractDdlParser;
/**
* @author laomei
*/
public abstract class AbstractMysqlDefaultValueTest {
private AbstractDdlParser parser;
private Tables tables;
private MySqlValueConverters converters;
protected Function<MySqlValueConverters, AbstractDdlParser> parserProducer;
@Before
public void beforeEach() {
converters = new MySqlValueConverters(JdbcValueConverters.DecimalMode.DOUBLE,
TemporalPrecisionMode.CONNECT,
JdbcValueConverters.BigIntUnsignedMode.LONG);
parser = parserProducer.apply(converters);
tables = new Tables();
}
@Test
public void parseUnsignedTinyintDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_TINYINT_TABLE (" +
" A TINYINT UNSIGNED NULL DEFAULT 0," +
" B TINYINT UNSIGNED NULL DEFAULT '10'," +
" C TINYINT UNSIGNED NULL," +
" D TINYINT UNSIGNED NOT NULL," +
" E TINYINT UNSIGNED NOT NULL DEFAULT 0," +
" F TINYINT UNSIGNED NOT NULL DEFAULT '0'" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_TINYINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo((short) 0);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo((short) 10);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("C").defaultValue()).isNull();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo((short) 0);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo((short) 0);
}
@Test
public void parseUnsignedSmallintDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_SMALLINT_TABLE (\n" +
" A SMALLINT UNSIGNED NULL DEFAULT 0,\n" +
" B SMALLINT UNSIGNED NULL DEFAULT '10',\n" +
" C SMALLINT UNSIGNED NULL,\n" +
" D SMALLINT UNSIGNED NOT NULL,\n" +
" E SMALLINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F SMALLINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_SMALLINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0);
}
@Test
public void parseUnsignedMediumintDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_MEDIUMINT_TABLE (\n" +
" A MEDIUMINT UNSIGNED NULL DEFAULT 0,\n" +
" B MEDIUMINT UNSIGNED NULL DEFAULT '10',\n" +
" C MEDIUMINT UNSIGNED NULL,\n" +
" D MEDIUMINT UNSIGNED NOT NULL,\n" +
" E MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F MEDIUMINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_MEDIUMINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0);
}
@Test
public void parseUnsignedIntDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_INT_TABLE (\n" +
" A INT UNSIGNED NULL DEFAULT 0,\n" +
" B INT UNSIGNED NULL DEFAULT '10',\n" +
" C INT UNSIGNED NULL,\n" +
" D INT UNSIGNED NOT NULL,\n" +
" E INT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F INT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_INT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10L);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0L);
}
@Test
public void parseUnsignedBigIntDefaultValueToLong() {
String sql = "CREATE TABLE UNSIGNED_BIGINT_TABLE (\n" +
" A BIGINT UNSIGNED NULL DEFAULT 0,\n" +
" B BIGINT UNSIGNED NULL DEFAULT '10',\n" +
" C BIGINT UNSIGNED NULL,\n" +
" D BIGINT UNSIGNED NOT NULL,\n" +
" E BIGINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F BIGINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_BIGINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10L);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0L);
}
@Test
public void parseUnsignedBigIntDefaultValueToBigDecimal() {
final MySqlValueConverters converters = new MySqlValueConverters(JdbcValueConverters.DecimalMode.DOUBLE,
TemporalPrecisionMode.CONNECT,
JdbcValueConverters.BigIntUnsignedMode.PRECISE);
final AbstractDdlParser parser = parserProducer.apply(converters);
String sql = "CREATE TABLE UNSIGNED_BIGINT_TABLE (\n" +
" A BIGINT UNSIGNED NULL DEFAULT 0,\n" +
" B BIGINT UNSIGNED NULL DEFAULT '10',\n" +
" C BIGINT UNSIGNED NULL,\n" +
" D BIGINT UNSIGNED NOT NULL,\n" +
" E BIGINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F BIGINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_BIGINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(BigDecimal.ZERO);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(new BigDecimal(10));
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(BigDecimal.ZERO);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(BigDecimal.ZERO);
}
@Test
public void parseStringDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_STRING_TABLE (\n" +
" A CHAR NULL DEFAULT 'A',\n" +
" B CHAR NULL DEFAULT 'b',\n" +
" C VARCHAR(10) NULL DEFAULT 'CC',\n" +
" D NCHAR(10) NULL DEFAULT '10',\n" +
" E NVARCHAR NULL DEFAULT '0',\n" +
" F CHAR DEFAULT NULL,\n" +
" G VARCHAR(10) DEFAULT NULL,\n" +
" H NCHAR(10) DEFAULT NULL\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_STRING_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo("A");
assertThat(table.columnWithName("B").defaultValue()).isEqualTo("b");
assertThat(table.columnWithName("C").defaultValue()).isEqualTo("CC");
assertThat(table.columnWithName("D").defaultValue()).isEqualTo("10");
assertThat(table.columnWithName("E").defaultValue()).isEqualTo("0");
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("G").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("H").defaultValue()).isEqualTo(null);
}
@Test
public void parseBitDefaultValue() {
String sql = "CREATE TABLE BIT_TABLE (\n" +
" A BIT(1) NULL DEFAULT NULL,\n" +
" B BIT(1) DEFAULT 0,\n" +
" C BIT(1) DEFAULT 1,\n" +
" D BIT(1) DEFAULT b'0',\n" +
" E BIT(1) DEFAULT b'1',\n" +
" F BIT(1) DEFAULT TRUE,\n" +
" G BIT(1) DEFAULT FALSE,\n" +
" H BIT(10) DEFAULT b'101000010',\n" +
" I BIT(10) DEFAULT NULL,\n" +
" J BIT(25) DEFAULT b'10110000100001111'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "BIT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("D").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("G").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("H").defaultValue()).isEqualTo(new byte[] {66, 1});
assertThat(table.columnWithName("I").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("J").defaultValue()).isEqualTo(new byte[] {15, 97, 1, 0});
}
@Test
public void parseBooleanDefaultValue() {
String sql = "CREATE TABLE BOOLEAN_TABLE (\n" +
" A BOOLEAN NULL DEFAULT 0,\n" +
" B BOOLEAN NOT NULL DEFAULT '1',\n" +
" C BOOLEAN NOT NULL DEFAULT '9',\n" +
" D BOOLEAN NOT NULL DEFAULT TRUE,\n" +
" E BOOLEAN DEFAULT NULL\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "BOOLEAN_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("D").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(null);
}
@Test
public void parseNumberDefaultValue() {
String sql = "CREATE TABLE NUMBER_TABLE (\n" +
" A TINYINT NULL DEFAULT 10,\n" +
" B SMALLINT NOT NULL DEFAULT '5',\n" +
" C INTEGER NOT NULL DEFAULT 0,\n" +
" D BIGINT NOT NULL DEFAULT 20,\n" +
" E INT NULL DEFAULT NULL,\n" +
" F FLOAT NULL DEFAULT 0,\n" +
" G DOUBLE NOT NULL DEFAULT 1.0\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "NUMBER_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo((short) 10);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo((short) 5);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("D").defaultValue()).isEqualTo(20L);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0d);
}
@Test
public void parseRealDefaultValue() {
String sql = "CREATE TABLE REAL_TABLE (\n" +
" A REAL NOT NULL DEFAULT 1,\n" +
" B REAL NULL DEFAULT NULL \n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "REAL_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(1f);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(null);
}
@Test
public void parseNumericAndDecimalToDoubleDefaultValue() {
String sql = "CREATE TABLE NUMERIC_DECIMAL_TABLE (\n" +
" A NUMERIC NOT NULL DEFAULT 1.23,\n" +
" B DECIMAL NOT NULL DEFAULT 2.321,\n" +
" C NUMERIC NULL DEFAULT '12.678'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "NUMERIC_DECIMAL_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(1.23d);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(2.321d);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(12.678d);
}
@Test
public void parseNumericAndDecimalToDecimalDefaultValue() {
final MySqlValueConverters converters = new MySqlValueConverters(JdbcValueConverters.DecimalMode.PRECISE,
TemporalPrecisionMode.CONNECT,
JdbcValueConverters.BigIntUnsignedMode.LONG);
final AbstractDdlParser parser = parserProducer.apply(converters);
String sql = "CREATE TABLE NUMERIC_DECIMAL_TABLE (\n" +
" A NUMERIC NOT NULL DEFAULT 1.23,\n" +
" B DECIMAL NOT NULL DEFAULT 2.321,\n" +
" C NUMERIC NULL DEFAULT '12.678'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "NUMERIC_DECIMAL_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(BigDecimal.valueOf(1.23));
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(BigDecimal.valueOf(2.321));
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(BigDecimal.valueOf(12.678));
}
}

View File

@ -253,7 +253,7 @@ public MysqlDdlParserWithSimpleTestListener(DdlChanges changesListener) {
}
public MysqlDdlParserWithSimpleTestListener(DdlChanges changesListener, boolean includeViews) {
super(false, includeViews);
super(false, includeViews, null);
this.ddlChanges = changesListener;
}
}

View File

@ -156,14 +156,20 @@ public void shouldParseCreateTableStatementWithCollate() {
@Test
@FixFor("DBZ-646")
public void shouldParseTokuDBTable() {
String ddl = "CREATE TABLE foo ( " + System.lineSeparator()
String ddl1 = "CREATE TABLE foo ( " + System.lineSeparator()
+ " c1 INTEGER NOT NULL, " + System.lineSeparator()
+ " c2 VARCHAR(22) " + System.lineSeparator()
+ ") engine=TokuDB `compression`=tokudb_zlib;";
parser.parse(ddl, tables);
assertThat(tables.size()).isEqualTo(1);
+ ") engine=TokuDB compression=tokudb_zlib;";
String ddl2 = "CREATE TABLE bar ( " + System.lineSeparator()
+ " c1 INTEGER NOT NULL, " + System.lineSeparator()
+ " c2 VARCHAR(22) " + System.lineSeparator()
+ ") engine=TokuDB compression='tokudb_zlib';";
parser.parse(ddl1 + ddl2, tables);
assertThat(tables.size()).isEqualTo(2);
listener.assertNext().createTableNamed("foo").ddlStartsWith("CREATE TABLE foo (");
listener.assertNext().createTableNamed("bar").ddlStartsWith("CREATE TABLE bar (");
parser.parse("DROP TABLE foo", tables);
parser.parse("DROP TABLE bar", tables);
assertThat(tables.size()).isEqualTo(0);
}
@ -490,22 +496,22 @@ public void shouldParseAlterTableStatementAddConstraintUniqueKey() {
parser.parse(ddl, tables);
assertThat(tables.size()).isEqualTo(1);
ddl = "ALTER TABLE t ADD CONSTRAINT UNIQUE KEY col_key ('col1');";
ddl = "ALTER TABLE t ADD CONSTRAINT UNIQUE KEY col_key (col1);";
parser.parse(ddl, tables);
ddl = "ALTER TABLE t ADD CONSTRAINT UNIQUE KEY ('col1');";
ddl = "ALTER TABLE t ADD CONSTRAINT UNIQUE KEY (col1);";
parser.parse(ddl, tables);
ddl = "ALTER TABLE t ADD UNIQUE KEY col_key ('col1');";
ddl = "ALTER TABLE t ADD UNIQUE KEY col_key (col1);";
parser.parse(ddl, tables);
ddl = "ALTER TABLE t ADD UNIQUE KEY ('col1');";
ddl = "ALTER TABLE t ADD UNIQUE KEY (col1);";
parser.parse(ddl, tables);
ddl = "ALTER TABLE t ADD CONSTRAINT 'xx' UNIQUE KEY col_key ('col1');";
ddl = "ALTER TABLE t ADD CONSTRAINT xx UNIQUE KEY col_key (col1);";
parser.parse(ddl, tables);
ddl = "ALTER TABLE t ADD CONSTRAINT 'xx' UNIQUE KEY ('col1');";
ddl = "ALTER TABLE t ADD CONSTRAINT xy UNIQUE KEY (col1);";
parser.parse(ddl, tables);
}
@ -819,11 +825,11 @@ public void shouldParseAndIgnoreCreateFunction() {
@FixFor("DBZ-667")
@Test
public void shouldParseScientificNotationNumber() {
String ddl = "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 1E-10, PRIMARY KEY (`id`));"
String ddl = "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 1E10, PRIMARY KEY (`id`));"
+ "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 1.3E-10, PRIMARY KEY (`id`));"
+ "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 1.3E+10, PRIMARY KEY (`id`));"
+ "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 1.4E+10, PRIMARY KEY (`id`));"
+ "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 3E10, PRIMARY KEY (`id`));"
+ "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 1.3e10, PRIMARY KEY (`id`))";
+ "CREATE TABLE t (id INT NOT NULL, myvalue DOUBLE DEFAULT 1.5e10, PRIMARY KEY (`id`))";
parser.parse(ddl, tables);
assertThat(tables.size()).isEqualTo(1);
}

View File

@ -0,0 +1,18 @@
/*
* Copyright Debezium Authors.
*
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package io.debezium.connector.mysql;
import io.debezium.connector.mysql.antlr.MySqlAntlrDdlParser;
/**
* @author Jiri Pechanec <jpechane@redhat.com>
*/
public class MysqlAntlrDefaultValueTest extends AbstractMysqlDefaultValueTest {
{
parserProducer = MySqlAntlrDdlParser::new;
}
}

View File

@ -5,322 +5,20 @@
*/
package io.debezium.connector.mysql;
import io.debezium.jdbc.JdbcValueConverters;
import io.debezium.jdbc.TemporalPrecisionMode;
import io.debezium.relational.Table;
import io.debezium.relational.TableId;
import io.debezium.relational.Tables;
import io.debezium.relational.ddl.SimpleDdlParserListener;
import org.junit.Before;
import org.junit.Test;
import java.math.BigDecimal;
import static org.fest.assertions.Assertions.assertThat;
/**
* @author laomei
*/
public class MysqlDefaultValueTest {
public class MysqlDefaultValueTest extends AbstractMysqlDefaultValueTest {
private MySqlDdlParser parser;
private Tables tables;
private SimpleDdlParserListener listener;
private MySqlValueConverters converters;
@Before
public void beforeEach() {
converters = new MySqlValueConverters(JdbcValueConverters.DecimalMode.DOUBLE,
TemporalPrecisionMode.CONNECT,
JdbcValueConverters.BigIntUnsignedMode.LONG);
parser = new MySqlDdlParser(false, converters);
tables = new Tables();
listener = new SimpleDdlParserListener();
parser.addListener(listener);
}
@Test
public void parseUnsignedTinyintDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_TINYINT_TABLE (" +
" A TINYINT UNSIGNED NULL DEFAULT 0," +
" B TINYINT UNSIGNED NULL DEFAULT '10'," +
" C TINYINT UNSIGNED NULL," +
" D TINYINT UNSIGNED NOT NULL," +
" E TINYINT UNSIGNED NOT NULL DEFAULT 0," +
" F TINYINT UNSIGNED NOT NULL DEFAULT '0'" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_TINYINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo((short) 0);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo((short) 10);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("C").defaultValue()).isNull();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo((short) 0);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo((short) 0);
}
@Test
public void parseUnsignedSmallintDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_SMALLINT_TABLE (\n" +
" A SMALLINT UNSIGNED NULL DEFAULT 0,\n" +
" B SMALLINT UNSIGNED NULL DEFAULT '10',\n" +
" C SMALLINT UNSIGNED NULL,\n" +
" D SMALLINT UNSIGNED NOT NULL,\n" +
" E SMALLINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F SMALLINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_SMALLINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0);
}
@Test
public void parseUnsignedMediumintDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_MEDIUMINT_TABLE (\n" +
" A MEDIUMINT UNSIGNED NULL DEFAULT 0,\n" +
" B MEDIUMINT UNSIGNED NULL DEFAULT '10',\n" +
" C MEDIUMINT UNSIGNED NULL,\n" +
" D MEDIUMINT UNSIGNED NOT NULL,\n" +
" E MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F MEDIUMINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_MEDIUMINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0);
}
@Test
public void parseUnsignedIntDefaultValue() {
String sql = "CREATE TABLE UNSIGNED_INT_TABLE (\n" +
" A INT UNSIGNED NULL DEFAULT 0,\n" +
" B INT UNSIGNED NULL DEFAULT '10',\n" +
" C INT UNSIGNED NULL,\n" +
" D INT UNSIGNED NOT NULL,\n" +
" E INT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F INT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_INT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10L);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0L);
}
@Test
public void parseUnsignedBigIntDefaultValueToLong() {
String sql = "CREATE TABLE UNSIGNED_BIGINT_TABLE (\n" +
" A BIGINT UNSIGNED NULL DEFAULT 0,\n" +
" B BIGINT UNSIGNED NULL DEFAULT '10',\n" +
" C BIGINT UNSIGNED NULL,\n" +
" D BIGINT UNSIGNED NOT NULL,\n" +
" E BIGINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F BIGINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_BIGINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(10L);
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(0L);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0L);
}
@Test
public void parseUnsignedBigIntDefaultValueToBigDecimal() {
converters = new MySqlValueConverters(JdbcValueConverters.DecimalMode.DOUBLE,
TemporalPrecisionMode.CONNECT,
JdbcValueConverters.BigIntUnsignedMode.PRECISE);
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE UNSIGNED_BIGINT_TABLE (\n" +
" A BIGINT UNSIGNED NULL DEFAULT 0,\n" +
" B BIGINT UNSIGNED NULL DEFAULT '10',\n" +
" C BIGINT UNSIGNED NULL,\n" +
" D BIGINT UNSIGNED NOT NULL,\n" +
" E BIGINT UNSIGNED NOT NULL DEFAULT 0,\n" +
" F BIGINT UNSIGNED NOT NULL DEFAULT '0'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_BIGINT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(BigDecimal.ZERO);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(new BigDecimal(10));
assertThat(table.columnWithName("C").isOptional()).isEqualTo(true);
assertThat(table.columnWithName("C").hasDefaultValue()).isTrue();
assertThat(table.columnWithName("D").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("D").hasDefaultValue()).isFalse();
assertThat(table.columnWithName("E").isOptional()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(BigDecimal.ZERO);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(BigDecimal.ZERO);
}
@Test
public void parseStringDefaultValue() {
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE UNSIGNED_STRING_TABLE (\n" +
" A CHAR NULL DEFAULT 'A',\n" +
" B CHAR NULL DEFAULT 'b',\n" +
" C VARCHAR(10) NULL DEFAULT 'CC',\n" +
" D NCHAR(10) NULL DEFAULT '10',\n" +
" E NVARCHAR NULL DEFAULT '0',\n" +
" F CHAR DEFAULT NULL,\n" +
" G VARCHAR(10) DEFAULT NULL,\n" +
" H NCHAR(10) DEFAULT NULL\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "UNSIGNED_STRING_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo("A");
assertThat(table.columnWithName("B").defaultValue()).isEqualTo("b");
assertThat(table.columnWithName("C").defaultValue()).isEqualTo("CC");
assertThat(table.columnWithName("D").defaultValue()).isEqualTo("10");
assertThat(table.columnWithName("E").defaultValue()).isEqualTo("0");
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("G").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("H").defaultValue()).isEqualTo(null);
}
@Test
public void parseBitDefaultValue() {
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE BIT_TABLE (\n" +
" A BIT(1) NULL DEFAULT NULL,\n" +
" B BIT(1) DEFAULT 0,\n" +
" C BIT(1) DEFAULT 1,\n" +
" D BIT(1) DEFAULT b'0',\n" +
" E BIT(1) DEFAULT b'1',\n" +
" F BIT(1) DEFAULT TRUE,\n" +
" G BIT(1) DEFAULT FALSE,\n" +
" H BIT(10) DEFAULT b'101000010',\n" +
" I BIT(10) DEFAULT NULL,\n" +
" J BIT(25) DEFAULT b'10110000100001111'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "BIT_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("D").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("G").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("H").defaultValue()).isEqualTo(new byte[] {66, 1});
assertThat(table.columnWithName("I").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("J").defaultValue()).isEqualTo(new byte[] {15, 97, 1, 0});
}
@Test
public void parseBooleanDefaultValue() {
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE BOOLEAN_TABLE (\n" +
" A BOOLEAN NULL DEFAULT 0,\n" +
" B BOOLEAN NOT NULL DEFAULT '1',\n" +
" C BOOLEAN NOT NULL DEFAULT '9',\n" +
" D BOOLEAN NOT NULL DEFAULT TRUE,\n" +
" E BOOLEAN DEFAULT NULL\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "BOOLEAN_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(false);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("D").defaultValue()).isEqualTo(true);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(null);
}
@Test
public void parseNumberDefaultValue() {
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE NUMBER_TABLE (\n" +
" A TINYINT NULL DEFAULT 10,\n" +
" B SMALLINT NOT NULL DEFAULT '5',\n" +
" C INTEGER NOT NULL DEFAULT 0,\n" +
" D BIGINT NOT NULL DEFAULT 20,\n" +
" E INT NULL DEFAULT NULL,\n" +
" F FLOAT NULL DEFAULT 0,\n" +
" G DOUBLE NOT NULL DEFAULT 1.0\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "NUMBER_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo((short) 10);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo((short) 5);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(0);
assertThat(table.columnWithName("D").defaultValue()).isEqualTo(20L);
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(null);
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(0d);
assertThat(table.columnWithName("G").defaultValue()).isEqualTo(1.0d);
}
@Test
public void parseRealDefaultValue() {
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE REAL_TABLE (\n" +
" A REAL NOT NULL DEFAULT 1,\n" +
" B REAL NULL DEFAULT NULL \n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "REAL_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(1f);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(null);
}
@Test
public void parseNumericAndDecimalToDoubleDefaultValue() {
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE NUMERIC_DECIMAL_TABLE (\n" +
" A NUMERIC NOT NULL DEFAULT 1.23,\n" +
" B DECIMAL NOT NULL DEFAULT 2.321,\n" +
" C NUMERIC NULL DEFAULT '12.678'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "NUMERIC_DECIMAL_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(1.23d);
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(2.321d);
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(12.678d);
}
@Test
public void parseNumericAndDecimalToDecimalDefaultValue() {
converters = new MySqlValueConverters(JdbcValueConverters.DecimalMode.PRECISE,
TemporalPrecisionMode.CONNECT,
JdbcValueConverters.BigIntUnsignedMode.LONG);
parser = new MySqlDdlParser(false, converters);
String sql = "CREATE TABLE NUMERIC_DECIMAL_TABLE (\n" +
" A NUMERIC NOT NULL DEFAULT 1.23,\n" +
" B DECIMAL NOT NULL DEFAULT 2.321,\n" +
" C NUMERIC NULL DEFAULT '12.678'\n" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "NUMERIC_DECIMAL_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo(BigDecimal.valueOf(1.23));
assertThat(table.columnWithName("B").defaultValue()).isEqualTo(BigDecimal.valueOf(2.321));
assertThat(table.columnWithName("C").defaultValue()).isEqualTo(BigDecimal.valueOf(12.678));
{
parserProducer = (converters) -> {
MySqlDdlParser parser = new MySqlDdlParser(false, converters);
listener = new SimpleDdlParserListener();
parser.addListener(listener);
return parser;
};
}
}

View File

@ -621,15 +621,16 @@ protected Object parseNumericLiteral(Marker start, boolean signed) {
sb.append(tokens.consumeInteger());
}
if (tokens.canConsume('.')) {
sb.append('.');
sb.append(tokens.consumeInteger());
decimal = true;
}
if (!tokens.canConsume('E')) {
if (!tokens.canConsumeAnyOf("E", "e")) {
if (decimal) return Double.parseDouble(sb.toString());
return Integer.parseInt(sb.toString());
}
sb.append('E');
if (tokens.matches("+", "-")) {
if (tokens.matchesAnyOf("+", "-")) {
sb.append(tokens.consumeAnyOf("+", "-"));
}
sb.append(tokens.consumeInteger());

View File

@ -61,6 +61,10 @@ protected static LocalDate toLocalDate(Object obj) {
// Assume the value is the epoch day number
return LocalDate.ofEpochDay((Long)obj);
}
if ( obj instanceof Integer) {
// Assume the value is the epoch day number
return LocalDate.ofEpochDay((Integer)obj);
}
throw new IllegalArgumentException("Unable to convert to LocalDate from unexpected value '" + obj + "' of type " + obj.getClass().getName());
}

View File

@ -65,6 +65,9 @@ public static Schema schema() {
* @throws IllegalArgumentException if the value is not an instance of the acceptable types
*/
public static long toEpochMillis(Object value, TemporalAdjuster adjuster) {
if (value instanceof Long) {
return (Long)value;
}
LocalDateTime dateTime = Conversions.toLocalDateTime(value);
if (adjuster != null) {
dateTime = dateTime.with(adjuster);

View File

@ -78,6 +78,9 @@ public static Schema schema() {
* @throws IllegalArgumentException if the value is not an instance of the acceptable types
*/
public static String toIsoString(Object value, ZoneId defaultZone, TemporalAdjuster adjuster) {
if (value instanceof String) {
return (String)value;
}
if (value instanceof OffsetDateTime) {
return toIsoString((OffsetDateTime) value, adjuster);
}

View File

@ -705,6 +705,7 @@ MYISAM: 'MYISAM';
NDB: 'NDB';
NDBCLUSTER: 'NDBCLUSTER';
PERFORMANCE_SCHEMA: 'PERFORMANCE_SCHEMA';
TOKUDB: 'TOKUDB';
// Transaction Levels
@ -1162,7 +1163,7 @@ fragment CHARSET_NAME: ARMSCII8 | ASCII | BIG5 | BINARY | CP1250
| UCS2 | UJIS | UTF16 | UTF16LE | UTF32
| UTF8 | UTF8MB4;
fragment EXPONENT_NUM_PART: 'E' '-'? DEC_DIGIT+;
fragment EXPONENT_NUM_PART: 'E' [\-+]? DEC_DIGIT+;
fragment ID_LITERAL: [A-Z_$0-9]*?[A-Z_$]+?[A-Z_$0-9]*;
fragment DQUOTA_STRING: '"' ( '\\'. | '""' | ~('"'| '\\') )* '"';
fragment SQUOTA_STRING: '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\'';

View File

@ -409,7 +409,7 @@ tableOption
| (CHECKSUM | PAGE_CHECKSUM) '='? boolValue=('0' | '1') #tableOptionChecksum
| DEFAULT? COLLATE '='? collationName #tableOptionCollate
| COMMENT '='? STRING_LITERAL #tableOptionComment
| COMPRESSION '='? STRING_LITERAL #tableOptionCompression
| COMPRESSION '='? (STRING_LITERAL | ID) #tableOptionCompression
| CONNECTION '='? STRING_LITERAL #tableOptionConnection
| DATA DIRECTORY '='? STRING_LITERAL #tableOptionDataDirectory
| DELAY_KEY_WRITE '='? boolValue=('0' | '1') #tableOptionDelay
@ -1877,6 +1877,7 @@ collationName
engineName
: ARCHIVE | BLACKHOLE | CSV | FEDERATED | INNODB | MEMORY
| MRG_MYISAM | MYISAM | NDB | NDBCLUSTER | PERFORMANCE_SCHEMA
| TOKUDB
;
uuidSet

View File

@ -296,7 +296,7 @@ public void taskStarted() {
engine.run();
});
try {
if (!latch.await(10, TimeUnit.SECONDS)) {
if (!latch.await(1000, TimeUnit.SECONDS)) {
// maybe it takes more time to start up, so just log a warning and continue
logger.warn("The connector did not finish starting its task(s) or complete in the expected amount of time");
}