/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jkiss.dbeaver.ext.mysql.model; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.ext.mysql.MySQLConstants; import org.jkiss.dbeaver.ext.mysql.MySQLUtils; import org.jkiss.dbeaver.model.DBPNamedObject2; import org.jkiss.dbeaver.model.DBPOrderedObject; import org.jkiss.dbeaver.model.DBUtils; import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils; import org.jkiss.dbeaver.model.impl.jdbc.struct.JDBCColumnKeyType; import org.jkiss.dbeaver.model.impl.jdbc.struct.JDBCTableColumn; import org.jkiss.dbeaver.model.meta.IPropertyValueListProvider; import org.jkiss.dbeaver.model.meta.Property; import org.jkiss.dbeaver.model.struct.DBSDataType; import org.jkiss.dbeaver.model.struct.DBSEntityAttribute; import org.jkiss.dbeaver.model.struct.rdb.DBSTableColumn; import org.jkiss.utils.CommonUtils; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * MySQLTableColumn */ public class MySQLTableColumn extends JDBCTableColumn<MySQLTableBase> implements DBSTableColumn, DBPNamedObject2, DBPOrderedObject { private static final Log log = Log.getLog(MySQLTableColumn.class); private static Pattern enumPattern = Pattern.compile("'([^']*)'"); public enum KeyType implements JDBCColumnKeyType { PRI, UNI, MUL; @Override public boolean isInUniqueKey() { return this == PRI || this == UNI; } @Override public boolean isInReferenceKey() { return this == MUL; } } private String comment; private long charLength; private MySQLCollation collation; private KeyType keyType; private String extraInfo; private String fullTypeName; private List<String> enumValues; public MySQLTableColumn(MySQLTableBase table) { super(table, false); } public MySQLTableColumn( MySQLTableBase table, ResultSet dbResult) throws DBException { super(table, true); loadInfo(dbResult); } // Copy constructor public MySQLTableColumn( MySQLTableBase table, DBSEntityAttribute source) throws DBException { super(table, source, false); this.comment = source.getDescription(); if (source instanceof MySQLTableColumn) { MySQLTableColumn mySource = (MySQLTableColumn)source; this.charLength = mySource.charLength; this.collation = mySource.collation; this.keyType = mySource.keyType; this.extraInfo = mySource.extraInfo; this.fullTypeName = mySource.fullTypeName; if (mySource.enumValues != null) { this.enumValues = new ArrayList<>(mySource.enumValues); } } else { this.collation = table.getContainer().getDefaultCollation(); this.fullTypeName = DBUtils.getFullTypeName(this); } } private void loadInfo(ResultSet dbResult) throws DBException { setName(JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_COLUMN_NAME)); setOrdinalPosition(JDBCUtils.safeGetInt(dbResult, MySQLConstants.COL_ORDINAL_POSITION)); String typeName = JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_DATA_TYPE); assert typeName != null; String keyTypeName = JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_COLUMN_KEY); if (!CommonUtils.isEmpty(keyTypeName)) { try { keyType = KeyType.valueOf(keyTypeName); } catch (IllegalArgumentException e) { log.debug(e); } } setTypeName(typeName); setValueType(MySQLUtils.typeNameToValueType(typeName)); DBSDataType dataType = getDataSource().getLocalDataType(typeName); this.charLength = JDBCUtils.safeGetLong(dbResult, MySQLConstants.COL_CHARACTER_MAXIMUM_LENGTH); if (this.charLength <= 0) { if (dataType != null) { setMaxLength(dataType.getPrecision()); } } else { setMaxLength(this.charLength); } this.comment = JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_COLUMN_COMMENT); setRequired(!"YES".equals(JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_IS_NULLABLE))); setScale(JDBCUtils.safeGetInt(dbResult, MySQLConstants.COL_NUMERIC_SCALE)); setPrecision(JDBCUtils.safeGetInt(dbResult, MySQLConstants.COL_NUMERIC_PRECISION)); String defaultValue = JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_COLUMN_DEFAULT); if (defaultValue != null) { switch (getDataKind()) { case STRING: defaultValue = "'" + defaultValue + "'"; break; case DATETIME: if (!defaultValue.isEmpty() && Character.isDigit(defaultValue.charAt(0))) { defaultValue = "'" + defaultValue + "'"; } break; } setDefaultValue(defaultValue); } this.collation = getDataSource().getCollation(JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_COLLATION_NAME)); this.extraInfo = JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_COLUMN_EXTRA); this.autoGenerated = extraInfo != null && extraInfo.contains(MySQLConstants.EXTRA_AUTO_INCREMENT); this.fullTypeName = JDBCUtils.safeGetString(dbResult, MySQLConstants.COL_COLUMN_TYPE); if (!CommonUtils.isEmpty(fullTypeName) && (isTypeEnum() || isTypeSet())) { enumValues = new ArrayList<>(); Matcher enumMatcher = enumPattern.matcher(fullTypeName); while (enumMatcher.find()) { String enumStr = enumMatcher.group(1); enumValues.add(enumStr); } } } @NotNull @Override public MySQLDataSource getDataSource() { return getTable().getDataSource(); } @Property(viewable = true, editable = true, updatable = true, order = 20, listProvider = ColumnTypeNameListProvider.class) public String getFullTypeName() { return fullTypeName; } public void setFullTypeName(String fullTypeName) { this.fullTypeName = fullTypeName; int divPos = fullTypeName.indexOf('('); if (divPos != -1) { super.setTypeName(fullTypeName.substring(0, divPos).trim()); } else { super.setTypeName(fullTypeName); } } @Override public String getTypeName() { return super.getTypeName(); } public boolean isTypeSet() { return typeName.equalsIgnoreCase(MySQLConstants.TYPE_NAME_SET); } public boolean isTypeEnum() { return typeName.equalsIgnoreCase(MySQLConstants.TYPE_NAME_ENUM); } //@Property(viewable = true, editable = true, updatable = true, order = 40) @Override public long getMaxLength() { return super.getMaxLength(); } @Override //@Property(viewable = true, order = 41) public int getScale() { return super.getScale(); } @Override //@Property(viewable = true, order = 42) public int getPrecision() { return super.getPrecision(); } @Property(viewable = true, editable = true, updatable = true, order = 50) @Override public boolean isRequired() { return super.isRequired(); } @Override @Property(viewable = true, editable = true, updatable = true, order = 51) public boolean isAutoGenerated() { return autoGenerated; } @Override @Property(viewable = true, editable = true, updatable = true, order = 70) public String getDefaultValue() { return super.getDefaultValue(); } @Property(viewable = true, editable = true, updatable = true, order = 71) public String getExtraInfo() { return extraInfo; } public void setExtraInfo(String extraInfo) { this.extraInfo = extraInfo; } @Override @Property(viewable = true, order = 60) public KeyType getKeyType() { return keyType; } public List<String> getEnumValues() { return enumValues; } @Property(viewable = false, editable = true, updatable = true, listProvider = CharsetListProvider.class, order = 81) public MySQLCharset getCharset() { return collation == null ? null : collation.getCharset(); } public void setCharset(MySQLCharset charset) { this.collation = charset == null ? null : charset.getDefaultCollation(); } @Property(viewable = false, editable = true, updatable = true, listProvider = CollationListProvider.class, order = 82) public MySQLCollation getCollation() { return collation; } public void setCollation(MySQLCollation collation) { this.collation = collation; } @Property(viewable = true, editable = true, updatable = true, order = 100) public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } @Nullable @Override public String getDescription() { return getComment(); } public static class CharsetListProvider implements IPropertyValueListProvider<MySQLTableColumn> { @Override public boolean allowCustomValue() { return false; } @Override public Object[] getPossibleValues(MySQLTableColumn object) { return object.getDataSource().getCharsets().toArray(); } } public static class CollationListProvider implements IPropertyValueListProvider<MySQLTableColumn> { @Override public boolean allowCustomValue() { return false; } @Override public Object[] getPossibleValues(MySQLTableColumn object) { if (object.getCharset() == null) { return new Object[0]; } else { return object.getCharset().getCollations().toArray(); } } } }