@@ -118,15 +118,81 @@ protected Statement createStatement(final ThreadContext context, final Connectio
118118 }
119119
120120 @ Override
121- protected IRubyObject indexes (final ThreadContext context , String tableName , final String name , String schemaName ) {
122- if ( tableName != null ) {
123- final int i = tableName .indexOf ('.' );
124- if ( i > 0 && schemaName == null ) {
125- schemaName = tableName .substring (0 , i );
126- tableName = tableName .substring (i + 1 );
121+ protected IRubyObject indexes (final ThreadContext context , String table , final String name , String schema ) {
122+ if ( table != null ) {
123+ final int i = table .indexOf ('.' );
124+ if ( i > 0 && schema == null ) {
125+ schema = table .substring (0 , i );
126+ table = table .substring (i + 1 );
127127 }
128128 }
129- return super .indexes (context , tableName , name , schemaName );
129+ final String tableName = table ;
130+ final String schemaName = schema ;
131+ // return super.indexes(context, tableName, name, schemaName);
132+ return withConnection (context , new Callable <IRubyObject >() {
133+ public RubyArray call (final Connection connection ) throws SQLException {
134+ final Ruby runtime = context .runtime ;
135+ final RubyClass indexDefinition = getIndexDefinition (runtime );
136+
137+ final TableName table = extractTableName (connection , schemaName , tableName );
138+
139+ final List <RubyString > primaryKeys = primaryKeys (context , connection , table );
140+
141+ final DatabaseMetaData metaData = connection .getMetaData ();
142+ ResultSet indexInfoSet = null ;
143+ try {
144+ indexInfoSet = metaData .getIndexInfo (table .catalog , table .schema , table .name , false , true );
145+ }
146+ catch (SQLException e ) {
147+ final String msg = e .getMessage ();
148+ if ( msg != null && msg .startsWith ("[SQLITE_ERROR] SQL error or missing database" ) ) {
149+ return RubyArray .newEmptyArray (runtime ); // on 3.8.7 getIndexInfo fails if table has no indexes
150+ }
151+ throw e ;
152+ }
153+ final RubyArray indexes = RubyArray .newArray (runtime , 8 );
154+ try {
155+ String currentIndex = null ;
156+
157+ while ( indexInfoSet .next () ) {
158+ String indexName = indexInfoSet .getString (INDEX_INFO_NAME );
159+ if ( indexName == null ) continue ;
160+
161+ final String columnName = indexInfoSet .getString (INDEX_INFO_COLUMN_NAME );
162+ final RubyString rubyColumnName = RubyString .newUnicodeString (runtime , columnName );
163+ if ( primaryKeys .contains (rubyColumnName ) ) continue ;
164+
165+ // We are working on a new index
166+ if ( ! indexName .equals (currentIndex ) ) {
167+ currentIndex = indexName ;
168+
169+ String indexTableName = indexInfoSet .getString (INDEX_INFO_TABLE_NAME );
170+
171+ final boolean nonUnique = indexInfoSet .getBoolean (INDEX_INFO_NON_UNIQUE );
172+
173+ IRubyObject [] args = new IRubyObject [] {
174+ RubyString .newUnicodeString (runtime , indexTableName ), // table_name
175+ RubyString .newUnicodeString (runtime , indexName ), // index_name
176+ runtime .newBoolean ( ! nonUnique ), // unique
177+ runtime .newArray () // [] for column names, we'll add to that in just a bit
178+ // orders, (since AR 3.2) where, type, using (AR 4.0)
179+ };
180+
181+ indexes .append ( indexDefinition .callMethod (context , "new" , args ) ); // IndexDefinition.new
182+ }
183+
184+ // One or more columns can be associated with an index
185+ IRubyObject lastIndexDef = indexes .isEmpty () ? null : indexes .entry (-1 );
186+ if ( lastIndexDef != null ) {
187+ ( (RubyArray ) lastIndexDef .callMethod (context , "columns" ) ).append (rubyColumnName );
188+ }
189+ }
190+
191+ return indexes ;
192+
193+ } finally { close (indexInfoSet ); }
194+ }
195+ });
130196 }
131197
132198 @ Override
0 commit comments