/* * 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.generic.model; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.ext.generic.GenericConstants; import org.jkiss.dbeaver.ext.generic.model.meta.GenericMetaObject; import org.jkiss.dbeaver.model.DBPEvaluationContext; import org.jkiss.dbeaver.model.DBUtils; import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet; import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession; import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement; import org.jkiss.dbeaver.model.impl.jdbc.JDBCConstants; import org.jkiss.dbeaver.model.impl.jdbc.cache.JDBCCompositeCache; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.struct.rdb.DBSIndexType; import org.jkiss.utils.CommonUtils; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.List; import java.util.Locale; /** * Index cache implementation */ class IndexCache extends JDBCCompositeCache<GenericStructContainer, GenericTable, GenericTableIndex, GenericTableIndexColumn> { private final GenericMetaObject indexObject; IndexCache(TableCache tableCache) { super( tableCache, GenericTable.class, GenericUtils.getColumn(tableCache.getDataSource(), GenericConstants.OBJECT_INDEX, JDBCConstants.TABLE_NAME), GenericUtils.getColumn(tableCache.getDataSource(), GenericConstants.OBJECT_INDEX, JDBCConstants.INDEX_NAME)); indexObject = tableCache.getDataSource().getMetaObject(GenericConstants.OBJECT_INDEX); } @NotNull @Override protected JDBCStatement prepareObjectsStatement(JDBCSession session, GenericStructContainer owner, GenericTable forParent) throws SQLException { try { return session.getMetaData().getIndexInfo( owner.getCatalog() == null ? null : owner.getCatalog().getName(), owner.getSchema() == null ? null : owner.getSchema().getName(), forParent == null ? owner.getDataSource().getAllObjectsPattern() : forParent.getName(), false, true).getSourceStatement(); } catch (SQLException e) { throw e; } catch (Exception e) { if (forParent == null) { throw new SQLException("Global indexes read not supported", e); } else { throw new SQLException(e); } } } @Nullable @Override protected GenericTableIndex fetchObject(JDBCSession session, GenericStructContainer owner, GenericTable parent, String indexName, JDBCResultSet dbResult) throws SQLException, DBException { boolean isNonUnique = GenericUtils.safeGetBoolean(indexObject, dbResult, JDBCConstants.NON_UNIQUE); String indexQualifier = GenericUtils.safeGetStringTrimmed(indexObject, dbResult, JDBCConstants.INDEX_QUALIFIER); long cardinality = GenericUtils.safeGetLong(indexObject, dbResult, JDBCConstants.INDEX_CARDINALITY); int indexTypeNum = GenericUtils.safeGetInt(indexObject, dbResult, JDBCConstants.TYPE); DBSIndexType indexType; switch (indexTypeNum) { case DatabaseMetaData.tableIndexStatistic: // Table index statistic. Not a real index. log.debug("Skip statistics index '" + indexName + "' in '" + DBUtils.getObjectFullName(parent, DBPEvaluationContext.DDL) + "'"); return null; // indexType = DBSIndexType.STATISTIC; break; case DatabaseMetaData.tableIndexClustered: indexType = DBSIndexType.CLUSTERED; break; case DatabaseMetaData.tableIndexHashed: indexType = DBSIndexType.HASHED; break; case DatabaseMetaData.tableIndexOther: indexType = DBSIndexType.OTHER; break; default: indexType = DBSIndexType.UNKNOWN; break; } if (CommonUtils.isEmpty(indexName)) { // [JDBC] Some drivers return empty index names indexName = parent.getName().toUpperCase(Locale.ENGLISH) + "_INDEX"; } return owner.getDataSource().getMetaModel().createIndexImpl( parent, isNonUnique, indexQualifier, cardinality, indexName, indexType, true); } @Nullable @Override protected GenericTableIndexColumn[] fetchObjectRow( JDBCSession session, GenericTable parent, GenericTableIndex object, JDBCResultSet dbResult) throws SQLException, DBException { int ordinalPosition = GenericUtils.safeGetInt(indexObject, dbResult, JDBCConstants.ORDINAL_POSITION); String columnName = GenericUtils.safeGetStringTrimmed(indexObject, dbResult, JDBCConstants.COLUMN_NAME); String ascOrDesc = GenericUtils.safeGetStringTrimmed(indexObject, dbResult, JDBCConstants.ASC_OR_DESC); if (ordinalPosition == 0 || CommonUtils.isEmpty(columnName)) { // Maybe a statistics index without column return null; } GenericTableColumn tableColumn = parent.getAttribute(session.getProgressMonitor(), columnName); if (tableColumn == null) { log.debug("Column '" + columnName + "' not found in table '" + parent.getName() + "' for index '" + object.getName() + "'"); return null; } return new GenericTableIndexColumn[] { new GenericTableIndexColumn( object, tableColumn, ordinalPosition, !"D".equalsIgnoreCase(ascOrDesc)) }; } @Override protected void cacheChildren(DBRProgressMonitor monitor, GenericTableIndex index, List<GenericTableIndexColumn> rows) { index.setColumns(rows); } }