/* * DBeaver - Universal Database Manager * Copyright (C) 2016-2016 Karl Griesser (fullref@gmail.com) * 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.exasol.model; import java.math.BigDecimal; import java.sql.ResultSet; import java.util.Collection; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.ext.exasol.editors.ExasolColumnDataTypeListProvider; import org.jkiss.dbeaver.model.DBPDataKind; import org.jkiss.dbeaver.model.DBPEvaluationContext; import org.jkiss.dbeaver.model.DBPHiddenObject; import org.jkiss.dbeaver.model.DBPNamedObject2; import org.jkiss.dbeaver.model.impl.DBPositiveNumberTransformer; 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.Property; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor; import org.jkiss.dbeaver.model.struct.DBSDataType; import org.jkiss.dbeaver.model.struct.DBSTypedObjectEx; import org.jkiss.dbeaver.model.struct.rdb.DBSTableColumn; import org.jkiss.utils.CommonUtils; public class ExasolTableColumn extends JDBCTableColumn<ExasolTableBase> implements DBSTableColumn, DBSTypedObjectEx, DBPHiddenObject, DBPNamedObject2, JDBCColumnKeyType { private ExasolDataType dataType; private Boolean identity; private BigDecimal identityValue; private String remarks; private Boolean isInDistKey; private String formatType; private Boolean changed = false; private Boolean oriRequired; // ----------------- // Constructors // ----------------- public ExasolTableColumn(DBRProgressMonitor monitor, ExasolTableBase tableBase, ResultSet dbResult) throws DBException { super(tableBase, true); this.formatType = JDBCUtils.safeGetString(dbResult, "COLUMN_TYPE"); setName(JDBCUtils.safeGetString(dbResult, "COLUMN_NAME")); setOrdinalPosition(JDBCUtils.safeGetInt(dbResult, "ORDINAL_POSITION")); setRequired(! JDBCUtils.safeGetBoolean(dbResult, "COLUMN_IS_NULLABLE")); setDefaultValue(JDBCUtils.safeGetString(dbResult, "COLUMN_DEF")); setMaxLength(JDBCUtils.safeGetInt(dbResult, "COLUMN_SIZE")); setScale(JDBCUtils.safeGetInt(dbResult, "DECIMAL_DIGITS")); this.isInDistKey = JDBCUtils.safeGetBoolean(dbResult, "COLUMN_IS_DISTRIBUTION_KEY"); this.identity = JDBCUtils.safeGetInteger(dbResult, "COLUMN_IDENTITY") == null ? false : true; if (identity) this.identityValue = JDBCUtils.safeGetBigDecimal(dbResult, "COLUMN_IDENTITY"); this.remarks = JDBCUtils.safeGetString(dbResult, "COLUMN_COMMENT"); this.dataType = tableBase.getDataSource().getDataType(monitor, JDBCUtils.safeGetString(dbResult, "TYPE_NAME")); // drivers > 5 have the issue that a cast from decimal without scale is made to matching integer in sql // so meta data queries have to handle this case if (tableBase.getDataSource().getDriverMajorVersion() > 5 && this.dataType.getName().equals("DECIMAL") && super.getScale() == 0) { if (super.getMaxLength() <= 4) { this.dataType = tableBase.getDataSource().getDataType(monitor,"SMALLINT"); } else if (super.getMaxLength() > 4 && super.getMaxLength() <= 9 ) { this.dataType = tableBase.getDataSource().getDataType(monitor,"INTEGER"); } else if (super.getMaxLength() > 9 && super.getMaxLength() <= 18 ) { this.dataType = tableBase.getDataSource().getDataType(monitor,"BIGINT"); } } this.changed = true; } public ExasolTableColumn(ExasolTableBase tableBase) { super(tableBase, false); setMaxLength(50L); setOrdinalPosition(-1); this.dataType = tableBase.getDataSource().getDataTypeCache().getCachedObject("VARCHAR"); setTypeName(dataType.getFullyQualifiedName(DBPEvaluationContext.DML)); setRequired(true); } // ----------------- // Business Contract // ----------------- @NotNull @Override public ExasolDataSource getDataSource() { return getTable().getDataSource(); } @Override public DBPDataKind getDataKind() { return dataType.getDataKind(); } @Override public String getTypeName() { return this.dataType.getName(); } @Override public int getTypeID() { return this.dataType.getTypeID(); } // ----------------- // Properties // ----------------- @Property(viewable = true, editable = false, order = 19) public ExasolTableBase getOwner() { return getTable(); } @Nullable @Property(viewable = true, editable = true, updatable = true, order = 21, listProvider = ExasolColumnDataTypeListProvider.class) public DBSDataType getDataType() { return dataType; } public void setDataType(ExasolDataType dataType) { if (!this.dataType.getTypeName().equals(dataType)) this.changed = true; this.dataType = dataType; } @Override @Property(viewable = true, editable = true, updatable = true, order = 38) public long getMaxLength() { return super.getMaxLength(); } public void setMaxLength(long maxLength) { if (this.maxLength != maxLength) this.changed = true; super.setMaxLength(maxLength); } @Override @Property(viewable = true, editable = true, updatable = true, valueRenderer = DBPositiveNumberTransformer.class, order = 39) public int getScale() { return super.getScale(); } public void setScale(int scale) { if (this.scale != scale) this.changed = true; super.setScale(scale); } @Property(viewable = true, editable = true, updatable = true, order = 46) @Nullable public BigDecimal getIdentityValue() { return this.identityValue; } public void setIdentityValue(BigDecimal identityValue) { this.identityValue = identityValue; } @Property(viewable = false, order = 40) public String getStringLength() { return ""; } @Override @Property(viewable = false, editable = true, updatable = true, valueRenderer = DBPositiveNumberTransformer.class, order = 42) public int getPrecision() { return super.getPrecision(); } public void setPrecision(int precision) { if (this.precision != precision) this.changed = true; super.precision = precision; this.precision = precision; } @Override @Property(viewable = true, order = 43, editable = true, updatable = true) public boolean isRequired() { return super.isRequired(); } public void setRequired(boolean required) { if (changed && oriRequired == null) oriRequired = super.isRequired(); super.setRequired(required); } @Override @Property(viewable = true, order = 44, editable = true, updatable = true) public String getDefaultValue() { return super.getDefaultValue(); } public void setDefaultValue(String defaultValue) { super.setDefaultValue(defaultValue); } public void setIdentity(Boolean identity) { this.identity = identity; } @Nullable @Override @Property(viewable = true, order = 999, editable = true, updatable = true) public String getDescription() { return remarks; } public void setDescription(String remarks) { this.remarks = remarks; } @Property(viewable = false, order = 121) public Boolean isDistKey() { return isInDistKey; } // no hidden columns supported in exasol @Override public boolean isHidden() { return false; } @Override @Property(viewable = true, editable = true, updatable = true, order = 45) public boolean isAutoGenerated() { return this.identity; } public void setAutoGenerated(Boolean identity) { this.identity = identity; } public String getFormatType() { if (changed) { switch (this.dataType.getTypeName()) { case "VARCHAR": case "CHAR": this.scale = 0; return dataType.getTypeName() + "(" + Long.toString(this.maxLength) + ")"; case "DECIMAL": return dataType.getTypeName() + "(" + Long.toString(this.maxLength) + "," + Long.toString(this.scale) + ")"; default: return dataType.getTypeName(); } } return this.formatType; } @Override @Property(viewable = true, order = 80) public boolean isInUniqueKey() { if (getTable().getClass() == ExasolView.class) { return false; } ExasolTableBase table = (ExasolTable) getTable(); try { final Collection<ExasolTableUniqueKey> uniqueKeysCache = table.getConstraints(new VoidProgressMonitor()); if (!CommonUtils.isEmpty(uniqueKeysCache)) { for (ExasolTableUniqueKey key : uniqueKeysCache) { if (key.hasColumn(this)) return true; } } } catch ( DBException e) { return false; } return false; } @Property(hidden = true) public Boolean isOriRequired() { return oriRequired; } @Override public boolean isInReferenceKey() { // don't need this one return false; } }