/*
* 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.model.impl.jdbc.struct;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.*;
import org.jkiss.dbeaver.model.data.DBDLabelValuePair;
import org.jkiss.dbeaver.model.data.DBDValueHandler;
import org.jkiss.dbeaver.model.exec.DBCResultSet;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.exec.DBCStatement;
import org.jkiss.dbeaver.model.exec.DBCStatementType;
import org.jkiss.dbeaver.model.impl.DBObjectNameCaseTransformer;
import org.jkiss.dbeaver.model.meta.IPropertyValueListProvider;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.struct.DBSAttributeEnumerable;
import org.jkiss.dbeaver.model.struct.DBSDataType;
import org.jkiss.dbeaver.model.struct.DBSEntity;
import org.jkiss.dbeaver.model.struct.DBSEntityAttribute;
import org.jkiss.dbeaver.model.struct.rdb.DBSTableColumn;
import org.jkiss.dbeaver.model.virtual.DBVUtils;
import org.jkiss.utils.CommonUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
/**
* JDBC abstract table column
*/
public abstract class JDBCTableColumn<TABLE_TYPE extends DBSEntity> extends JDBCAttribute implements DBSTableColumn, DBSAttributeEnumerable, DBPSaveableObject {
private final TABLE_TYPE table;
private boolean persisted;
private String defaultValue;
protected JDBCTableColumn(TABLE_TYPE table, boolean persisted)
{
this.table = table;
this.persisted = persisted;
}
protected JDBCTableColumn(
TABLE_TYPE table,
boolean persisted,
String name,
String typeName,
int valueType,
int ordinalPosition,
long maxLength,
int scale,
int precision,
boolean required,
boolean autoGenerated,
String defaultValue)
{
super(name, typeName, valueType, ordinalPosition, maxLength, scale, precision, required, autoGenerated);
this.defaultValue = defaultValue;
this.table = table;
this.persisted = persisted;
}
protected JDBCTableColumn(
TABLE_TYPE table,
DBSEntityAttribute source,
boolean persisted)
{
super(source);
this.table = table;
this.persisted = persisted;
this.defaultValue = source.getDefaultValue();
}
public TABLE_TYPE getTable()
{
return table;
}
@NotNull
@Override
public TABLE_TYPE getParentObject()
{
return getTable();
}
@NotNull
@Property(viewable = true, editable = true, valueTransformer = DBObjectNameCaseTransformer.class, order = 10)
@Override
public String getName()
{
return super.getName();
}
@Property(viewable = true, editable = true, order = 20, listProvider = ColumnTypeNameListProvider.class)
@Override
public String getTypeName()
{
return super.getTypeName();
}
@Override
public void setTypeName(String typeName) {
super.setTypeName(typeName);
final DBPDataSource dataSource = getDataSource();
if (dataSource instanceof DBPDataTypeProvider) {
DBSDataType dataType = ((DBPDataTypeProvider) dataSource).getLocalDataType(typeName);
if (dataType != null) {
this.valueType = dataType.getTypeID();
}
}
}
@Property(viewable = true, editable = true, order = 40)
@Override
public long getMaxLength()
{
return super.getMaxLength();
}
@Property(viewable = true, editable = true, order = 50)
@Override
public boolean isRequired()
{
return super.isRequired();
}
@Property(viewable = true, editable = true, order = 70)
@Override
public String getDefaultValue()
{
return defaultValue;
}
public void setDefaultValue(String defaultValue)
{
this.defaultValue = defaultValue;
}
@Override
public boolean isPersisted()
{
return persisted;
}
@Override
public void setPersisted(boolean persisted)
{
this.persisted = persisted;
}
@NotNull
@Override
public Collection<DBDLabelValuePair> getValueEnumeration(@NotNull DBCSession session, @Nullable Object valuePattern, int maxResults) throws DBException {
DBDValueHandler valueHandler = DBUtils.findValueHandler(session, this);
StringBuilder query = new StringBuilder();
query.append("SELECT ").append(DBUtils.getQuotedIdentifier(this)).append(", count(*)");
// Do not use description columns because they duplicate distinct value
// String descColumns = DBVUtils.getDictionaryDescriptionColumns(session.getProgressMonitor(), this);
// if (descColumns != null) {
// query.append(", ").append(descColumns);
// }
query.append("\nFROM ").append(DBUtils.getObjectFullName(getTable(), DBPEvaluationContext.DML));
if (valuePattern instanceof String) {
query.append("\nWHERE ").append(DBUtils.getQuotedIdentifier(this)).append(" LIKE ?");
}
query.append("\nGROUP BY ").append(DBUtils.getQuotedIdentifier(this));
try (DBCStatement dbStat = session.prepareStatement(DBCStatementType.QUERY, query.toString(), false, false, false)) {
if (valuePattern instanceof String) {
valueHandler.bindValueObject(session, dbStat, this, 0, "%" + valuePattern + "%");
}
dbStat.setLimit(0, maxResults);
if (dbStat.executeStatement()) {
try (DBCResultSet dbResult = dbStat.openResultSet()) {
return DBVUtils.readDictionaryRows(session, this, valueHandler, dbResult);
}
} else {
return Collections.emptyList();
}
}
}
public static class ColumnTypeNameListProvider implements IPropertyValueListProvider<JDBCTableColumn> {
@Override
public boolean allowCustomValue()
{
return true;
}
@Override
public Object[] getPossibleValues(JDBCTableColumn column)
{
Set<String> typeNames = new TreeSet<>();
if (column.getDataSource() instanceof DBPDataTypeProvider) {
for (DBSDataType type : ((DBPDataTypeProvider) column.getDataSource()).getLocalDataTypes()) {
if (type.getDataKind() != DBPDataKind.UNKNOWN && !CommonUtils.isEmpty(type.getName()) && Character.isLetter(type.getName().charAt(0))) {
typeNames.add(type.getName());
}
}
}
return typeNames.toArray(new String[typeNames.size()]);
}
}
}