From 5c9e7184366184873719ef58b34681c0a1f67083 Mon Sep 17 00:00:00 2001 From: rkuchar Date: Sun, 29 Apr 2018 16:33:52 +0200 Subject: [PATCH] DBZ-252 uncomment getting ddl parser instance from configuration + improve/refactor dataType resolver for ANTLR --- .../debezium/connector/mysql/MySqlSchema.java | 15 +- .../relational/ddl/DataTypeBuilder.java | 101 +++++++++ .../relational/ddl/DataTypeGrammarParser.java | 86 +------- .../io/debezium/antlr/AntlrDdlParser.java | 2 +- .../io/debezium/antlr/DataTypeResolver.java | 102 ++++++++- .../antlr/mysql/MySqlAntlrDdlParser.java | 194 ++++++++---------- 6 files changed, 289 insertions(+), 211 deletions(-) create mode 100644 debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeBuilder.java diff --git a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlSchema.java b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlSchema.java index aec874330..6f851a76e 100644 --- a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlSchema.java +++ b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlSchema.java @@ -102,15 +102,14 @@ public MySqlSchema(Configuration config, String serverName, Predicate gt 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.ddlParser = new MySqlAntlrDdlParser(); + try { + this.ddlParser = parsingMode.getParserClass().newInstance(); this.ddlChanges = this.ddlParser.getDdlChanges(); -// } -// catch (InstantiationException | IllegalAccessException e) { -// // ddl parser constructor 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()); -// } + } + 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); diff --git a/debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeBuilder.java b/debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeBuilder.java new file mode 100644 index 000000000..48519e741 --- /dev/null +++ b/debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeBuilder.java @@ -0,0 +1,101 @@ +/* + * 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.relational.ddl; + +import java.sql.Types; + +/** + * @author Roman Kuchár . + */ +public class DataTypeBuilder { + private StringBuilder prefix = new StringBuilder(); + private StringBuilder suffix = new StringBuilder(); + private String parameters; + private int jdbcType = Types.NULL; + private long length = -1; + private int scale = -1; + private int arrayDimsLength = 0; + private final int[] arrayDims = new int[40]; + + public void addToName(String str) { + if (length == -1) { + // Length hasn't been set yet, so add to the prefix ... + if (prefix.length() != 0) prefix.append(' '); + prefix.append(str); + } else { + // Length has already been set, so add as a suffix ... + if (suffix.length() != 0) suffix.append(' '); + suffix.append(str); + } + } + + public DataTypeBuilder jdbcType(int jdbcType) { + this.jdbcType = jdbcType; + return this; + } + + public DataTypeBuilder parameters(String parameters) { + this.parameters = parameters; + return this; + } + + public DataTypeBuilder length(long length) { + this.length = length; + return this; + } + + public DataTypeBuilder scale(int scale) { + this.scale = scale; + return this; + } + + public DataTypeBuilder addArrayDimension(int dimension) { + arrayDims[arrayDimsLength++] = dimension; + return this; + } + + public DataTypeBuilder reset() { + length = -1; + scale = -1; + arrayDimsLength = 0; + prefix.setLength(0); + suffix.setLength(0); + return this; + } + + public DataType create() { + StringBuilder name = new StringBuilder(this.prefix); + StringBuilder expression = new StringBuilder(this.prefix); + if (length != -1) { + expression.append('('); + expression.append(this.length); + if (scale != -1) { + expression.append(','); + expression.append(this.scale); + } + expression.append(')'); + } else if (parameters != null ) { + expression.append('('); + expression.append(parameters); + expression.append(')'); + } + if (arrayDimsLength != 0) { + for (int i = 0; i != arrayDimsLength; ++i) { + expression.append('['); + expression.append(this.arrayDims[i]); + expression.append(']'); + } + } + if (suffix.length() != 0) { + expression.append(' '); + expression.append(suffix); + name.append(' '); + name.append(suffix); + } + return new DataType(expression.toString(), name.toString(), jdbcType, length, scale, arrayDims, arrayDimsLength); + } +} \ No newline at end of file diff --git a/debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeGrammarParser.java b/debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeGrammarParser.java index 145097b04..29a4926e0 100644 --- a/debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeGrammarParser.java +++ b/debezium-core/src/main/java/io/debezium/relational/ddl/DataTypeGrammarParser.java @@ -87,7 +87,7 @@ public DataType match(TokenStream stream) { */ public DataType match(TokenStream stream, Consumer errors) { builder.reset(); - builder.jdbcType = jdbcType; + builder.jdbcType(jdbcType); if (pattern.match(stream, builder, errors != null ? errors : (e) -> {})) { return builder.create(); } @@ -240,90 +240,6 @@ protected Pattern parseScaleLiteral(TokenStream stream) throws ParsingException } - protected static class DataTypeBuilder { - private StringBuilder prefix = new StringBuilder(); - private StringBuilder suffix = new StringBuilder(); - private String parameters; - private int jdbcType = Types.NULL; - private long length = -1; - private int scale = -1; - private int arrayDimsLength = 0; - private final int[] arrayDims = new int[40]; - - public void addToName(String str) { - if (length == -1) { - // Length hasn't been set yet, so add to the prefix ... - if (prefix.length() != 0) prefix.append(' '); - prefix.append(str); - } else { - // Length has already been set, so add as a suffix ... - if (suffix.length() != 0) suffix.append(' '); - suffix.append(str); - } - } - - public DataTypeBuilder parameters(String parameters) { - this.parameters = parameters; - return this; - } - - public DataTypeBuilder length(long length) { - this.length = length; - return this; - } - - public DataTypeBuilder scale(int scale) { - this.scale = scale; - return this; - } - - public DataTypeBuilder addArrayDimension(int dimension) { - arrayDims[arrayDimsLength++] = dimension; - return this; - } - - public DataTypeBuilder reset() { - length = -1; - scale = -1; - arrayDimsLength = 0; - prefix.setLength(0); - suffix.setLength(0); - return this; - } - - public DataType create() { - StringBuilder name = new StringBuilder(this.prefix); - StringBuilder expression = new StringBuilder(this.prefix); - if (length != -1) { - expression.append('('); - expression.append(this.length); - if (scale != -1) { - expression.append(','); - expression.append(this.scale); - } - expression.append(')'); - } else if (parameters != null ) { - expression.append('('); - expression.append(parameters); - expression.append(')'); - } - if (arrayDimsLength != 0) { - for (int i = 0; i != arrayDimsLength; ++i) { - expression.append('['); - expression.append(this.arrayDims[i]); - expression.append(']'); - } - } - if (suffix.length() != 0) { - expression.append(' '); - expression.append(suffix); - name.append(' '); - name.append(suffix); - } - return new DataType(expression.toString(), name.toString(), jdbcType, length, scale, arrayDims, arrayDimsLength); - } - } - protected static interface Pattern { boolean match(TokenStream stream, DataTypeBuilder builder, Consumer error); diff --git a/debezium-ddl-parser/src/main/java/io/debezium/antlr/AntlrDdlParser.java b/debezium-ddl-parser/src/main/java/io/debezium/antlr/AntlrDdlParser.java index af7e24a90..55faebe24 100644 --- a/debezium-ddl-parser/src/main/java/io/debezium/antlr/AntlrDdlParser.java +++ b/debezium-ddl-parser/src/main/java/io/debezium/antlr/AntlrDdlParser.java @@ -122,7 +122,7 @@ public Collection getParsingExceptionsFromWalker() { * @param ctx the parser rule context; may not be null * @return matched part of the getText */ - protected String getText(ParserRuleContext ctx) { + public static String getText(ParserRuleContext ctx) { Interval interval = new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()); return ctx.start.getInputStream().getText(interval); } diff --git a/debezium-ddl-parser/src/main/java/io/debezium/antlr/DataTypeResolver.java b/debezium-ddl-parser/src/main/java/io/debezium/antlr/DataTypeResolver.java index a9a4b12a2..9b9ade22d 100644 --- a/debezium-ddl-parser/src/main/java/io/debezium/antlr/DataTypeResolver.java +++ b/debezium-ddl-parser/src/main/java/io/debezium/antlr/DataTypeResolver.java @@ -6,9 +6,12 @@ package io.debezium.antlr; +import io.debezium.relational.ddl.DataType; +import io.debezium.relational.ddl.DataTypeBuilder; +import io.debezium.text.ParsingException; import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.TerminalNode; -import java.sql.Types; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -27,30 +30,107 @@ public void registerDataTypes(String contextClassCanonicalName, DataTypeEntry da dataTypeEntries.add(dataTypeEntry); } - public Integer resolveDataType(ParserRuleContext dataTypeContext) { + public DataType resolveDataType(ParserRuleContext dataTypeContext) { + DataType dataType = null; + // use priority according to number of matched tokens + int selectedTypePriority = -1; for (DataTypeEntry dataTypeEntry : contextDataTypesMap.get(dataTypeContext.getClass().getCanonicalName())) { - if (dataTypeContext.getToken(dataTypeEntry.getDbmsDataTypeTokenIdentifier(), 0) != null) { - return dataTypeEntry.getJdbcDataType(); + int dataTypePriority = dataTypeEntry.getDbmsDataTypeTokenIdentifiers().length; + if (dataTypePriority > selectedTypePriority) { + DataTypeBuilder dataTypeBuilder = new DataTypeBuilder(); + boolean correctDataType = true; + for (Integer mainTokenIdentifier : dataTypeEntry.getDbmsDataTypeTokenIdentifiers()) { + TerminalNode token = dataTypeContext.getToken(mainTokenIdentifier, 0); + if (correctDataType) { + if (token == null) { + correctDataType = false; + } + else { + dataTypeBuilder.addToName(token.getText()); + } + } + } + if (correctDataType) { + addOptionalSuffixToName(dataTypeContext, dataTypeEntry, dataTypeBuilder); + dataTypeBuilder.jdbcType(dataTypeEntry.getJdbcDataType()); + dataTypeBuilder.length(dataTypeEntry.getDefaultLength()); + dataTypeBuilder.scale(dataTypeEntry.getDefaultScale()); + + dataType = dataTypeBuilder.create(); + selectedTypePriority = dataTypePriority; + } + } + } + if (dataType == null) { + throw new ParsingException(null, "Unrecognized dataType for " + AntlrDdlParser.getText(dataTypeContext)); + } + return dataType; + } + + private void addOptionalSuffixToName(ParserRuleContext dataTypeContext, DataTypeEntry dataTypeEntry, DataTypeBuilder dataTypeBuilder) { + if (dataTypeEntry.getSuffixTokens() != null) { + for (Integer suffixTokenIdentifier : dataTypeEntry.getSuffixTokens()) { + if (dataTypeContext.getToken(suffixTokenIdentifier, 0) != null) { + dataTypeBuilder.addToName(dataTypeContext.getToken(suffixTokenIdentifier, 0).getText()); + } } } - return Types.NULL; } public static class DataTypeEntry { - private final int dbmsDataTypeTokenIdentifier; - private final int jdbcDataType; - public DataTypeEntry(int dbmsDataTypeTokenIdentifier, int jdbcDataType) { - this.dbmsDataTypeTokenIdentifier = dbmsDataTypeTokenIdentifier; + /** + * Token identifiers for DBMS data type + */ + private final Integer[] dbmsDataTypeTokenIdentifiers; + /** + * Mapped JDBC data type + */ + private final int jdbcDataType; + private Integer[] suffixTokens = null; + private int defaultLength = -1; + private int defaultScale = -1; + + public DataTypeEntry(int jdbcDataType, Integer... dbmsDataTypeTokenIdentifiers) { + this.dbmsDataTypeTokenIdentifiers = dbmsDataTypeTokenIdentifiers; this.jdbcDataType = jdbcDataType; } - public int getDbmsDataTypeTokenIdentifier() { - return dbmsDataTypeTokenIdentifier; + public Integer[] getDbmsDataTypeTokenIdentifiers() { + return dbmsDataTypeTokenIdentifiers; } public int getJdbcDataType() { return jdbcDataType; } + + public Integer[] getSuffixTokens() { + return suffixTokens; + } + + public int getDefaultLength() { + return defaultLength; + } + + public int getDefaultScale() { + return defaultScale; + } + + public DataTypeEntry setSuffixTokens(Integer... suffixTokens) { + this.suffixTokens = suffixTokens; + return this; + } + + public DataTypeEntry setDefualtLengthDimmension(int defaultLength) { + this.defaultLength = defaultLength; + return this; + } + + public DataTypeEntry setDefualtLengthScaleDimmension(int defaultLength, int defaultScale) { + this.defaultLength = defaultLength; + this.defaultScale = defaultScale; + return this; + } + } } diff --git a/debezium-ddl-parser/src/main/java/io/debezium/antlr/mysql/MySqlAntlrDdlParser.java b/debezium-ddl-parser/src/main/java/io/debezium/antlr/mysql/MySqlAntlrDdlParser.java index e88d35f7e..7d8b8bf24 100644 --- a/debezium-ddl-parser/src/main/java/io/debezium/antlr/mysql/MySqlAntlrDdlParser.java +++ b/debezium-ddl-parser/src/main/java/io/debezium/antlr/mysql/MySqlAntlrDdlParser.java @@ -21,6 +21,7 @@ import io.debezium.relational.Table; import io.debezium.relational.TableEditor; import io.debezium.relational.TableId; +import io.debezium.relational.ddl.DataType; import io.debezium.text.ParsingException; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CommonTokenStream; @@ -109,68 +110,93 @@ protected boolean isGrammarInUpperCase() { @Override protected void initDataTypes(DataTypeResolver dataTypeResolver) { dataTypeResolver.registerDataTypes(MySqlParser.StringDataTypeContext.class.getCanonicalName(), Arrays.asList( - new DataTypeEntry(MySqlParser.CHAR, Types.CHAR), - new DataTypeEntry(MySqlParser.VARCHAR, Types.VARCHAR), - new DataTypeEntry(MySqlParser.TINYTEXT, Types.VARCHAR), - new DataTypeEntry(MySqlParser.TEXT, Types.VARCHAR), - new DataTypeEntry(MySqlParser.MEDIUMTEXT, Types.VARCHAR), - new DataTypeEntry(MySqlParser.LONGTEXT, Types.VARCHAR), - new DataTypeEntry(MySqlParser.NCHAR, Types.NCHAR), - new DataTypeEntry(MySqlParser.NVARCHAR, Types.NVARCHAR) + new DataTypeEntry(Types.CHAR, MySqlParser.CHAR), + new DataTypeEntry(Types.VARCHAR, MySqlParser.VARCHAR), + new DataTypeEntry(Types.VARCHAR, MySqlParser.TINYTEXT), + new DataTypeEntry(Types.VARCHAR, MySqlParser.TEXT), + new DataTypeEntry(Types.VARCHAR, MySqlParser.MEDIUMTEXT), + new DataTypeEntry(Types.VARCHAR, MySqlParser.LONGTEXT), + new DataTypeEntry(Types.NCHAR, MySqlParser.NCHAR), + new DataTypeEntry(Types.NVARCHAR, MySqlParser.NVARCHAR), + new DataTypeEntry(Types.BINARY, MySqlParser.CHAR, MySqlParser.BINARY), + new DataTypeEntry(Types.BINARY, MySqlParser.VARCHAR, MySqlParser.BINARY), + new DataTypeEntry(Types.BINARY, MySqlParser.TINYTEXT, MySqlParser.BINARY), + new DataTypeEntry(Types.BINARY, MySqlParser.TEXT, MySqlParser.BINARY), + new DataTypeEntry(Types.BINARY, MySqlParser.MEDIUMTEXT, MySqlParser.BINARY), + new DataTypeEntry(Types.BINARY, MySqlParser.LONGTEXT, MySqlParser.BINARY), + new DataTypeEntry(Types.BINARY, MySqlParser.NCHAR, MySqlParser.BINARY), + new DataTypeEntry(Types.BINARY, MySqlParser.NVARCHAR, MySqlParser.BINARY) )); dataTypeResolver.registerDataTypes(MySqlParser.NationalStringDataTypeContext.class.getCanonicalName(), Arrays.asList( - new DataTypeEntry(MySqlParser.VARCHAR, Types.NVARCHAR), - new DataTypeEntry(MySqlParser.CHARACTER, Types.NCHAR) + new DataTypeEntry(Types.NVARCHAR, MySqlParser.NATIONAL, MySqlParser.VARCHAR).setSuffixTokens(MySqlParser.BINARY), + new DataTypeEntry(Types.NCHAR, MySqlParser.NATIONAL, MySqlParser.CHARACTER).setSuffixTokens(MySqlParser.BINARY), + new DataTypeEntry(Types.NVARCHAR, MySqlParser.NCHAR, MySqlParser.VARCHAR).setSuffixTokens(MySqlParser.BINARY) )); dataTypeResolver.registerDataTypes(MySqlParser.NationalVaryingStringDataTypeContext.class.getCanonicalName(), Arrays.asList( - new DataTypeEntry(MySqlParser.CHAR, Types.NVARCHAR), - new DataTypeEntry(MySqlParser.CHARACTER, Types.NVARCHAR) + new DataTypeEntry(Types.NVARCHAR, MySqlParser.NATIONAL, MySqlParser.CHAR, MySqlParser.VARYING), + new DataTypeEntry(Types.NVARCHAR, MySqlParser.NATIONAL, MySqlParser.CHARACTER, MySqlParser.VARYING) )); dataTypeResolver.registerDataTypes(MySqlParser.DimensionDataTypeContext.class.getCanonicalName(), Arrays.asList( - new DataTypeEntry(MySqlParser.TINYINT, Types.SMALLINT), - new DataTypeEntry(MySqlParser.SMALLINT, Types.SMALLINT), - new DataTypeEntry(MySqlParser.MEDIUMINT, Types.INTEGER), - new DataTypeEntry(MySqlParser.INT, Types.INTEGER), - new DataTypeEntry(MySqlParser.INTEGER, Types.INTEGER), - new DataTypeEntry(MySqlParser.BIGINT, Types.BIGINT), - new DataTypeEntry(MySqlParser.REAL, Types.REAL), - new DataTypeEntry(MySqlParser.DOUBLE, Types.DOUBLE), - new DataTypeEntry(MySqlParser.FLOAT, Types.FLOAT), - new DataTypeEntry(MySqlParser.DECIMAL, Types.DECIMAL), - new DataTypeEntry(MySqlParser.DEC, Types.DECIMAL), - new DataTypeEntry(MySqlParser.FIXED, Types.DECIMAL), - new DataTypeEntry(MySqlParser.NUMERIC, Types.NUMERIC), - new DataTypeEntry(MySqlParser.BIT, Types.BIT), - new DataTypeEntry(MySqlParser.TIME, Types.TIME), - new DataTypeEntry(MySqlParser.TIMESTAMP, Types.TIMESTAMP_WITH_TIMEZONE), - new DataTypeEntry(MySqlParser.DATETIME, Types.TIMESTAMP), - new DataTypeEntry(MySqlParser.BINARY, Types.BINARY), - new DataTypeEntry(MySqlParser.VARBINARY, Types.VARBINARY), - new DataTypeEntry(MySqlParser.YEAR, Types.INTEGER) + new DataTypeEntry(Types.SMALLINT, MySqlParser.TINYINT) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.SMALLINT, MySqlParser.SMALLINT) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.INTEGER, MySqlParser.MEDIUMINT) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.INTEGER, MySqlParser.INT) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.INTEGER, MySqlParser.INTEGER) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.BIGINT, MySqlParser.BIGINT) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.REAL, MySqlParser.REAL) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.DOUBLE, MySqlParser.DOUBLE) + .setSuffixTokens(MySqlParser.PRECISION, MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.FLOAT, MySqlParser.FLOAT) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.DECIMAL, MySqlParser.DECIMAL) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL) + .setDefualtLengthScaleDimmension(10, 0), + new DataTypeEntry(Types.DECIMAL, MySqlParser.DEC) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL) + .setDefualtLengthScaleDimmension(10, 0), + new DataTypeEntry(Types.DECIMAL, MySqlParser.FIXED) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL) + .setDefualtLengthScaleDimmension(10, 0), + new DataTypeEntry(Types.NUMERIC, MySqlParser.NUMERIC) + .setSuffixTokens(MySqlParser.SIGNED, MySqlParser.UNSIGNED, MySqlParser.ZEROFILL), + new DataTypeEntry(Types.BIT, MySqlParser.BIT), + new DataTypeEntry(Types.TIME, MySqlParser.TIME), + new DataTypeEntry(Types.TIMESTAMP_WITH_TIMEZONE, MySqlParser.TIMESTAMP), + new DataTypeEntry(Types.TIMESTAMP, MySqlParser.DATETIME), + new DataTypeEntry(Types.BINARY, MySqlParser.BINARY), + new DataTypeEntry(Types.VARBINARY, MySqlParser.VARBINARY), + new DataTypeEntry(Types.INTEGER, MySqlParser.YEAR) )); dataTypeResolver.registerDataTypes(MySqlParser.SimpleDataTypeContext.class.getCanonicalName(), Arrays.asList( - new DataTypeEntry(MySqlParser.DATE, Types.DATE), - new DataTypeEntry(MySqlParser.TINYBLOB, Types.BLOB), - new DataTypeEntry(MySqlParser.BLOB, Types.BLOB), - new DataTypeEntry(MySqlParser.MEDIUMBLOB, Types.BLOB), - new DataTypeEntry(MySqlParser.LONGBLOB, Types.BLOB), - new DataTypeEntry(MySqlParser.BOOL, Types.BOOLEAN), - new DataTypeEntry(MySqlParser.BOOLEAN, Types.BOOLEAN) + new DataTypeEntry(Types.DATE, MySqlParser.DATE), + new DataTypeEntry(Types.BLOB, MySqlParser.TINYBLOB), + new DataTypeEntry(Types.BLOB, MySqlParser.BLOB), + new DataTypeEntry(Types.BLOB, MySqlParser.MEDIUMBLOB), + new DataTypeEntry(Types.BLOB, MySqlParser.LONGBLOB), + new DataTypeEntry(Types.BOOLEAN, MySqlParser.BOOL), + new DataTypeEntry(Types.BOOLEAN, MySqlParser.BOOLEAN) )); dataTypeResolver.registerDataTypes(MySqlParser.CollectionDataTypeContext.class.getCanonicalName(), Arrays.asList( - new DataTypeEntry(MySqlParser.ENUM, Types.CHAR), - new DataTypeEntry(MySqlParser.SET, Types.CHAR) + new DataTypeEntry(Types.CHAR, MySqlParser.ENUM).setSuffixTokens(MySqlParser.BINARY), + new DataTypeEntry(Types.CHAR, MySqlParser.SET).setSuffixTokens(MySqlParser.BINARY) )); dataTypeResolver.registerDataTypes(MySqlParser.SpatialDataTypeContext.class.getCanonicalName(), Arrays.asList( - new DataTypeEntry(MySqlParser.GEOMETRYCOLLECTION, Types.OTHER), - new DataTypeEntry(MySqlParser.LINESTRING, Types.OTHER), - new DataTypeEntry(MySqlParser.MULTILINESTRING, Types.OTHER), - new DataTypeEntry(MySqlParser.MULTIPOINT, Types.OTHER), - new DataTypeEntry(MySqlParser.MULTIPOLYGON, Types.OTHER), - new DataTypeEntry(MySqlParser.POINT, Types.OTHER), - new DataTypeEntry(MySqlParser.POLYGON, Types.OTHER), - new DataTypeEntry(MySqlParser.JSON, Types.OTHER), - new DataTypeEntry(MySqlParser.GEOMETRY, Types.OTHER) + new DataTypeEntry(Types.OTHER, MySqlParser.GEOMETRYCOLLECTION), + new DataTypeEntry(Types.OTHER, MySqlParser.LINESTRING), + new DataTypeEntry(Types.OTHER, MySqlParser.MULTILINESTRING), + new DataTypeEntry(Types.OTHER, MySqlParser.MULTIPOINT), + new DataTypeEntry(Types.OTHER, MySqlParser.MULTIPOLYGON), + new DataTypeEntry(Types.OTHER, MySqlParser.POINT), + new DataTypeEntry(Types.OTHER, MySqlParser.POLYGON), + new DataTypeEntry(Types.OTHER, MySqlParser.JSON), + new DataTypeEntry(Types.OTHER, MySqlParser.GEOMETRY) )); } @@ -200,17 +226,11 @@ private String getFullTableName(TableId tableId) { } private void resolveColumnDataType(MySqlParser.DataTypeContext dataTypeContext) { - String dataTypeName; String charsetName = null; - Integer jdbcDataType = Types.NULL; + DataType dataType = dataTypeResolver.resolveDataType(dataTypeContext); + if (dataTypeContext instanceof MySqlParser.StringDataTypeContext) { MySqlParser.StringDataTypeContext stringDataTypeContext = (MySqlParser.StringDataTypeContext) dataTypeContext; - dataTypeName = stringDataTypeContext.typeName.getText(); - if (stringDataTypeContext.BINARY() != null) { - // TODO rkuchar: figure out something better - jdbcDataType = Types.BINARY; - dataTypeName += " " + stringDataTypeContext.BINARY().getText(); - } if (stringDataTypeContext.lengthOneDimension() != null) { Integer length = Integer.valueOf(stringDataTypeContext.lengthOneDimension().decimalLiteral().getText()); @@ -223,16 +243,6 @@ private void resolveColumnDataType(MySqlParser.DataTypeContext dataTypeContext) } else if (dataTypeContext instanceof MySqlParser.NationalStringDataTypeContext) { MySqlParser.NationalStringDataTypeContext nationalStringDataTypeContext = (MySqlParser.NationalStringDataTypeContext) dataTypeContext; - dataTypeName = nationalStringDataTypeContext.typeName.getText(); - if (nationalStringDataTypeContext.NATIONAL() != null) { - dataTypeName = nationalStringDataTypeContext.NATIONAL().getText() + " " + dataTypeName; - } - if (nationalStringDataTypeContext.NCHAR() != null) { - dataTypeName = nationalStringDataTypeContext.NCHAR().getText() + " " + dataTypeName; - } - if (nationalStringDataTypeContext.BINARY() != null) { - dataTypeName = dataTypeName + " " + nationalStringDataTypeContext.BINARY().getText(); - } if (nationalStringDataTypeContext.lengthOneDimension() != null) { Integer length = Integer.valueOf(nationalStringDataTypeContext.lengthOneDimension().decimalLiteral().getText()); @@ -242,10 +252,6 @@ else if (dataTypeContext instanceof MySqlParser.NationalStringDataTypeContext) { else if (dataTypeContext instanceof MySqlParser.NationalVaryingStringDataTypeContext) { MySqlParser.NationalVaryingStringDataTypeContext nationalVaryingStringDataTypeContext = (MySqlParser.NationalVaryingStringDataTypeContext) dataTypeContext; - dataTypeName = nationalVaryingStringDataTypeContext.NATIONAL().getText() - + " " + nationalVaryingStringDataTypeContext.typeName.getText() - + " " + nationalVaryingStringDataTypeContext.VARYING().getText(); - if (nationalVaryingStringDataTypeContext.lengthOneDimension() != null) { Integer length = Integer.valueOf(nationalVaryingStringDataTypeContext.lengthOneDimension().decimalLiteral().getText()); columnEditor.length(length); @@ -253,19 +259,6 @@ else if (dataTypeContext instanceof MySqlParser.NationalVaryingStringDataTypeCon } else if (dataTypeContext instanceof MySqlParser.DimensionDataTypeContext) { MySqlParser.DimensionDataTypeContext dimensionDataTypeContext = (MySqlParser.DimensionDataTypeContext) dataTypeContext; - dataTypeName = dimensionDataTypeContext.typeName.getText(); - if (dimensionDataTypeContext.PRECISION() != null) { - dataTypeName += " " + dimensionDataTypeContext.PRECISION().getText(); - } - if (dimensionDataTypeContext.SIGNED() != null) { - dataTypeName += " " + dimensionDataTypeContext.SIGNED().getText(); - } - if (dimensionDataTypeContext.UNSIGNED() != null) { - dataTypeName += " " + dimensionDataTypeContext.UNSIGNED().getText(); - } - if (dimensionDataTypeContext.ZEROFILL() != null) { - dataTypeName += " " + dimensionDataTypeContext.ZEROFILL().getText(); - } Integer length = null; Integer scale = null; @@ -294,16 +287,13 @@ else if (dataTypeContext instanceof MySqlParser.DimensionDataTypeContext) { columnEditor.scale(scale); } } - else if (dataTypeContext instanceof MySqlParser.SimpleDataTypeContext) { - dataTypeName = ((MySqlParser.SimpleDataTypeContext) dataTypeContext).typeName.getText(); - } else if (dataTypeContext instanceof MySqlParser.CollectionDataTypeContext) { MySqlParser.CollectionDataTypeContext collectionDataTypeContext = (MySqlParser.CollectionDataTypeContext) dataTypeContext; if (collectionDataTypeContext.charsetName() != null) { charsetName = collectionDataTypeContext.charsetName().getText(); } - dataTypeName = collectionDataTypeContext.typeName.getText(); - if (dataTypeName.equals("SET")) { + + if (dataType.name().equals("SET")) { // After DBZ-132, it will always be comma seperated columnEditor.length(Math.max(0, collectionDataTypeContext.collectionOption().size() * 2 - 1)); // number of options + number of commas } @@ -311,12 +301,8 @@ else if (dataTypeContext instanceof MySqlParser.CollectionDataTypeContext) { columnEditor.length(1); } } - else if (dataTypeContext instanceof MySqlParser.SpatialDataTypeContext) { - dataTypeName = ((MySqlParser.SpatialDataTypeContext) dataTypeContext).typeName.getText(); - } - else { - throw new IllegalStateException("Not recognized instance of data type context for " + dataTypeContext.getText()); - } + + String dataTypeName = dataType.name(); if (dataTypeName.equals("ENUM") || dataTypeName.equals("SET")) { // type expression has to be set, because the value converter needs to know the enum or set options @@ -326,18 +312,14 @@ else if (dataTypeContext instanceof MySqlParser.SpatialDataTypeContext) { columnEditor.type(dataTypeName.toUpperCase()); } - if (jdbcDataType == Types.NULL) { - jdbcDataType = dataTypeResolver.resolveDataType(dataTypeContext); - } + int jdbcDataType = dataType.jdbcType(); columnEditor.jdbcType(jdbcDataType); - if (Types.DECIMAL == jdbcDataType) { - if (columnEditor.length() == -1) { - columnEditor.length(10); - } - if (columnEditor.scale() == -1) { - columnEditor.scale(0); - } + if (columnEditor.length() == -1) { + columnEditor.length((int) dataType.length()); + } + if (columnEditor.scale() == -1) { + columnEditor.scale(dataType.scale()); } if (Types.NCHAR == jdbcDataType || Types.NVARCHAR == jdbcDataType) { // NCHAR and NVARCHAR columns always uses utf8 as charset