class JcrMetaData implements DatabaseMetaData {

    @SuppressWarnings( "unchecked" )
    @Override
    public ResultSet getIndexInfo( String catalog,
                                   String schema,
                                   String tableNamePattern,
                                   boolean unique,
                                   boolean approximate ) throws SQLException {

        // Get index information for all tables if tableNamePattern is null
        if (tableNamePattern == null) tableNamePattern = WILDCARD;

        Map<?, Object>[] metadataList = new Map[JDBCColumnPositions.INDEX_INFO.MAX_COLUMNS];
        metadataList[0] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.TABLE_CAT,
                                                             JcrType.DefaultDataTypes.STRING,
                                                             ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);
        metadataList[1] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.TABLE_SCHEM,
                                                             JcrType.DefaultDataTypes.STRING,
                                                             ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);
        metadataList[2] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.TABLE_NAME,
                                                             JcrType.DefaultDataTypes.STRING,
                                                             ResultsMetadataConstants.NULL_TYPES.NOT_NULL, this.connection);
        metadataList[3] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.NON_UNIQUE,
                                                             JcrType.DefaultDataTypes.BOOLEAN,
                                                             ResultsMetadataConstants.NULL_TYPES.NOT_NULL, this.connection);
        metadataList[4] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.INDEX_QUALIFIER,
                                                             JcrType.DefaultDataTypes.STRING,
                                                             ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);
        metadataList[5] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.INDEX_NAME,
                                                             JcrType.DefaultDataTypes.STRING,
                                                             ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);
        metadataList[6] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.TYPE,
                                                             JcrType.DefaultDataTypes.LONG,
                                                             ResultsMetadataConstants.NULL_TYPES.NOT_NULL, this.connection);
        metadataList[7] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.ORDINAL_POSITION,
                                                             JcrType.DefaultDataTypes.LONG,
                                                             ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);
        metadataList[8] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.COLUMN_NAME,
                                                             JcrType.DefaultDataTypes.LONG,
                                                             ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);
        metadataList[9] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.ASC_OR_DESC,
                                                             JcrType.DefaultDataTypes.STRING,
                                                             ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);

        metadataList[10] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.CARDINALITY,
                                                              JcrType.DefaultDataTypes.LONG,
                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL, this.connection);
        metadataList[11] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.PAGES,
                                                              JcrType.DefaultDataTypes.LONG,
                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL, this.connection);
        metadataList[12] = MetadataProvider.getColumnMetadata(catalogName, null, JDBCColumnNames.INDEX_INFO.FILTER_CONDITION,
                                                              JcrType.DefaultDataTypes.STRING,
                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE, this.connection);

        try {
            Boolean nonUnique = Boolean.FALSE;
            List<List<?>> records = new ArrayList<List<?>>();
            for (NodeType type : filterNodeTypes(tableNamePattern)) {
                // Create a unique key for each "jcr:uuid" property, so do this only for those node types
                // that somehow extend "mix:referenceable" ...
                if (!type.isNodeType("mix:referenceable")) continue;

                // Every table has a "jcr:path" pseudo-column that is the primary key ...
                List<Object> currentRow = new ArrayList<Object>(JDBCColumnPositions.INDEX_INFO.MAX_COLUMNS);
                currentRow.add(catalogName); // TABLE_CAT
                currentRow.add("NULL"); // TABLE_SCHEM
                currentRow.add(type.getName()); // TABLE_NAME
                currentRow.add(nonUnique); // NON_UNIQUE
                currentRow.add(catalogName); // INDEX_QUALIFIER
                currentRow.add(type.getName() + "_UK"); // INDEX_NAME
                currentRow.add(DatabaseMetaData.tableIndexHashed); // TYPE
                currentRow.add((short)1); // ORDINAL_POSITION
                currentRow.add(type.getName()); // COLUMN_NAME
                currentRow.add("A"); // ASC_OR_DESC
                currentRow.add(0); // CARDINALITY
                currentRow.add(1); // PAGES
                currentRow.add(null); // FILTER_CONDITION

                // add the current row to the list of records.
                records.add(currentRow);
            }

            JcrStatement jcrstmt = new JcrStatement(this.connection);
            MetadataProvider provider = new MetadataProvider(metadataList);
            ResultSetMetaDataImpl resultSetMetaData = new ResultSetMetaDataImpl(provider);
            QueryResult queryresult = MetaDataQueryResult.createResultSet(records, resultSetMetaData);
            return new JcrResultSet(jcrstmt, queryresult, resultSetMetaData);
        } catch (RepositoryException e) {
            throw new SQLException(e.getLocalizedMessage());
        }
    }

    public  JcrMetaData( JcrConnection connection );

}