001 package com.sptci.rwt;
002
003 import java.sql.Connection;
004 import java.sql.DatabaseMetaData;
005 import java.sql.ResultSet;
006 import java.sql.SQLException;
007
008 import java.util.ArrayList;
009 import java.util.Collection;
010 import java.util.TreeMap;
011
012 import com.sptci.util.CloseJDBCResources;
013
014 /**
015 * An analyser for analysing index columns for tables in the database.
016 *
017 * <p>© Copyright 2007 <a href='http://sptci.com/' target='_new'>Sans Pareil Technologies, Inc.</a></p>
018 * @author Rakesh Vidyadharan 2007-09-25
019 * @version $Id: IndexAnalyser.java 4123 2008-05-25 21:49:01Z rakesh $
020 * @see java.sql.DatabaseMetaData#getIndexInfo
021 */
022 public class IndexAnalyser extends KeyAnalyser
023 {
024 /**
025 * Create a new instance of the class using the specified connection
026 * manager.
027 *
028 * @param manager The manager for obtaining database connections.
029 */
030 public IndexAnalyser( final ConnectionManager manager )
031 {
032 super( manager );
033 }
034
035 /**
036 * Returns a collection of {@link IndexMetaData} objects that
037 * contain all information pertaining to the indices for the
038 * specified table.
039 *
040 * @see Analyser#analyse
041 * @see #getNames
042 * @param parameters Must contain two parameters which are the names of
043 * the <code>catalog/schema</code> and table from which index metadata
044 * are to be retrieved.
045 */
046 @Override
047 public Collection<IndexMetaData> analyse( final MetaData... parameters )
048 throws SQLException
049 {
050 final TreeMap<String,IndexMetaData> md =
051 new TreeMap<String,IndexMetaData>();
052 Connection connection = null;
053 ResultSet resultSet = null;
054
055 try
056 {
057 final CatalogueSchema cs = getNames( parameters[0] );
058 final TableMetaData tmd = (TableMetaData) parameters[1];
059
060 connection = manager.open();
061 final DatabaseMetaData dmd = connection.getMetaData();
062 resultSet = dmd.getIndexInfo(
063 cs.getCatalogue(), cs.getSchema(), tmd.getName(), false, false );
064
065 boolean first = true;
066 while ( resultSet.next() )
067 {
068 if ( first )
069 {
070 checkTableColumns( tmd );
071 first = false;
072 }
073
074 final String name = resultSet.getString( "index_name" );
075 if ( name != null )
076 {
077 IndexMetaData imd = md.get( name );
078
079 if ( imd == null )
080 {
081 imd = new IndexMetaData();
082 imd.setName( name );
083 imd.setUnique( ! resultSet.getBoolean( "non_unique" ) );
084 imd.setType( processType( resultSet.getShort( "type" ) ) );
085 imd.setPages( resultSet.getInt( "pages" ) );
086 imd.setCardinality( resultSet.getInt( "cardinality" ) );
087 imd.setSortSequence(
088 processSortSequence( resultSet.getString( "asc_or_desc" ) ) );
089 imd.setTable( tmd );
090
091 md.put( name, imd );
092 }
093
094 imd.addColumn( tmd.getColumn( resultSet.getString( "column_name" ) ) );
095 }
096 }
097
098 tmd.addIndices( md.values() );
099 }
100 finally
101 {
102 CloseJDBCResources.close( resultSet );
103 CloseJDBCResources.close( connection );
104 }
105
106 return md.values();
107 }
108
109 /**
110 * Process the <code>type</code> values and match
111 * them with the appropriate {@link IndexMetaData.Type} value.
112 *
113 * @param value The the short value read from result set.
114 * @return The appropriate type value.
115 */
116 protected IndexMetaData.Type processType( final short value )
117 {
118 IndexMetaData.Type rule = null;
119
120 switch ( value )
121 {
122 case DatabaseMetaData.tableIndexStatistic :
123 rule = IndexMetaData.Type.Statistic;
124 break;
125 case DatabaseMetaData.tableIndexClustered :
126 rule = IndexMetaData.Type.Clustered;
127 break;
128 case DatabaseMetaData.tableIndexHashed :
129 rule = IndexMetaData.Type.Hashed;
130 break;
131 case DatabaseMetaData.tableIndexOther :
132 rule = IndexMetaData.Type.Other;
133 break;
134 };
135
136 return rule;
137 }
138
139 /**
140 * Process the <code>asc_or_desc</code> value and match them with the
141 * appropriate {@link IndexMetaData.SortSequence} value.
142 *
143 * @param value The the short value read from result set.
144 * @return The appropriate sort order value.
145 */
146 protected IndexMetaData.SortSequence processSortSequence(
147 final String value )
148 {
149 IndexMetaData.SortSequence order = null;
150
151 if ( "A".equalsIgnoreCase( value ) )
152 {
153 order = IndexMetaData.SortSequence.Ascending;
154 }
155 else if ( "D".equalsIgnoreCase( value ) )
156 {
157 order = IndexMetaData.SortSequence.Descending;
158 }
159 else
160 {
161 order = IndexMetaData.SortSequence.Unsorted;
162 }
163
164 return order;
165 }
166 }