SQLiteIndex extends AbstractAttributeIndex<A, O> implements SortedKeyStatisticsAttributeIndex<A, O>, NonHeapTypeIndex { @Override public void init(ObjectStore<O> objectStore, QueryOptions queryOptions) { final ConnectionManager connectionManager = getConnectionManager(queryOptions); final Connection connection = connectionManager.getConnection(this, queryOptions); pragmaJournalMode = DBQueries.getPragmaJournalModeOrNull(connection); pragmaSynchronous = DBQueries.getPragmaSynchronousOrNull(connection); canModifySyncAndJournaling = pragmaJournalMode != null && pragmaSynchronous != null; doAddAll(ObjectSet.fromObjectStore(objectStore, queryOptions), queryOptions, true); } SQLiteIndex(final Attribute<O, A> attribute,
                       final SimpleAttribute<O, K> primaryKeyAttribute,
                       final SimpleAttribute<K, O> foreignKeyAttribute,
                       final String tableNameSuffix); @Override boolean supportsQuery(Query<O> query, QueryOptions queryOptions); @Override boolean isMutable(); @Override boolean isQuantized(); @Override Index<O> getEffectiveIndex(); @Override ResultSet<O> retrieve(final Query<O> query, final QueryOptions queryOptions); @Override boolean addAll(final ObjectSet<O> objectSet, final QueryOptions queryOptions); @Override boolean removeAll(final ObjectSet<O> objectSet, final QueryOptions queryOptions); @Override void clear(QueryOptions queryOptions); @Override void init(ObjectStore<O> objectStore, QueryOptions queryOptions); @Override void destroy(QueryOptions queryOptions); @Override CloseableIterable<A> getDistinctKeys(final QueryOptions queryOptions); @Override CloseableIterable<A> getDistinctKeys(A lowerBound, boolean lowerInclusive, A upperBound, boolean upperInclusive, final QueryOptions queryOptions); @Override CloseableIterable<A> getDistinctKeysDescending(QueryOptions queryOptions); @Override CloseableIterable<A> getDistinctKeysDescending(A lowerBound, boolean lowerInclusive, A upperBound, boolean upperInclusive, QueryOptions queryOptions); @Override Integer getCountOfDistinctKeys(QueryOptions queryOptions); @Override CloseableIterable<KeyStatistics<A>> getStatisticsForDistinctKeysDescending(QueryOptions queryOptions); @Override CloseableIterable<KeyStatistics<A>> getStatisticsForDistinctKeys(QueryOptions queryOptions); @Override CloseableIterable<KeyValue<A, O>> getKeysAndValues(final QueryOptions queryOptions); @Override CloseableIterable<KeyValue<A, O>> getKeysAndValues(A lowerBound, boolean lowerInclusive, A upperBound, boolean upperInclusive, final QueryOptions queryOptions); @Override CloseableIterable<KeyValue<A, O>> getKeysAndValuesDescending(QueryOptions queryOptions); @Override CloseableIterable<KeyValue<A, O>> getKeysAndValuesDescending(A lowerBound, boolean lowerInclusive, A upperBound, boolean upperInclusive, QueryOptions queryOptions); @Override Integer getCountForKey(A key, QueryOptions queryOptions); @Override boolean equals(Object o); @Override int hashCode(); static SQLiteIndex<A, O, K> onAttribute(final Attribute<O, A> attribute,
                                                                                   final SimpleAttribute<O, K> objectKeyAttribute,
                                                                                   final SimpleAttribute<K, O> foreignKeyAttribute);  }
@Test public void testInit_ApplyUpdateForIndexIsFalse() throws Exception{ ConnectionManager connectionManager = mock(ConnectionManager.class); Connection connection = mock(Connection.class); when(connectionManager.getConnection(any(SQLiteIndex.class), anyQueryOptions())).thenReturn(connection); when(connectionManager.isApplyUpdateForIndexEnabled(any(SQLiteIndex.class))).thenReturn(false); Statement statement = mock(Statement.class); when(connection.createStatement()).thenReturn(statement); java.sql.ResultSet journalModeRs = mock(java.sql.ResultSet.class); java.sql.ResultSet synchronousRs = mock(java.sql.ResultSet.class); when(journalModeRs.next()).thenReturn(true).thenReturn(false); when(synchronousRs.next()).thenReturn(true).thenReturn(false); when(journalModeRs.getString(1)).thenReturn("DELETE"); when(synchronousRs.getInt(1)).thenReturn(2); when(statement.executeQuery("PRAGMA journal_mode;")).thenReturn(journalModeRs); when(statement.executeQuery("PRAGMA synchronous;")).thenReturn(synchronousRs); SQLiteIndex<String, Car, Integer> carFeaturesOffHeapIndex = new SQLiteIndex<String, Car, Integer>( Car.FEATURES, OBJECT_TO_ID, ID_TO_OBJECT, "" ); carFeaturesOffHeapIndex.init(emptyObjectStore(), createQueryOptions(connectionManager)); verify(statement, times(1)).executeQuery("PRAGMA journal_mode;"); verify(statement, times(1)).executeQuery("PRAGMA synchronous;"); verify(statement, times(2)).close(); Assert.assertEquals(carFeaturesOffHeapIndex.pragmaSynchronous, SQLiteConfig.SynchronousMode.FULL); Assert.assertEquals(carFeaturesOffHeapIndex.pragmaJournalMode, SQLiteConfig.JournalMode.DELETE); Assert.assertTrue(carFeaturesOffHeapIndex.canModifySyncAndJournaling); }
@Test public void testInit_IndexTableExists() throws Exception{ ConnectionManager connectionManager = mock(ConnectionManager.class); Connection connection = mock(Connection.class); Statement statement = mock(Statement.class); PreparedStatement preparedStatement = mock(PreparedStatement.class); java.sql.ResultSet tableCheckRs = mock(java.sql.ResultSet.class); java.sql.ResultSet journalModeRs = mock(java.sql.ResultSet.class); java.sql.ResultSet synchronousRs = mock(java.sql.ResultSet.class); when(tableCheckRs.next()).thenReturn(true); when(journalModeRs.next()).thenReturn(true).thenReturn(false); when(synchronousRs.next()).thenReturn(true).thenReturn(false); when(journalModeRs.getString(1)).thenReturn("DELETE"); when(synchronousRs.getInt(1)).thenReturn(2); when(statement.executeQuery("SELECT 1 FROM sqlite_master WHERE type='table' AND name='cqtbl_features';")).thenReturn(tableCheckRs); when(statement.executeQuery("PRAGMA journal_mode;")).thenReturn(journalModeRs); when(statement.executeQuery("PRAGMA synchronous;")).thenReturn(synchronousRs); when(connection.prepareStatement("INSERT OR IGNORE INTO " + TABLE_NAME + " values(?, ?);")).thenReturn(preparedStatement); when(connectionManager.getConnection(any(SQLiteIndex.class), anyQueryOptions())).thenReturn(connection); when(connectionManager.isApplyUpdateForIndexEnabled(any(SQLiteIndex.class))).thenReturn(true); when(connection.createStatement()).thenReturn(statement); when(preparedStatement.executeBatch()).thenReturn(new int[] {2}); Set<Car> initWithObjects = new HashSet<Car>(2); initWithObjects.add(new Car(1, "Ford", "Focus", Car.Color.BLUE, 5, 9000.50, Arrays.asList("abs", "gps"), Collections.emptyList())); initWithObjects.add(new Car(2, "Honda", "Civic", Car.Color.RED, 5, 5000.00, Arrays.asList("airbags"), Collections.emptyList())); SQLiteIndex<String, Car, Integer> carFeaturesOffHeapIndex = new SQLiteIndex<String, Car, Integer>( Car.FEATURES, OBJECT_TO_ID, ID_TO_OBJECT, "" ); carFeaturesOffHeapIndex.init(wrappingObjectStore(initWithObjects), createQueryOptions(connectionManager)); verify(statement, times(1)).executeQuery("PRAGMA journal_mode;"); verify(statement, times(1)).executeQuery("PRAGMA synchronous;"); verify(statement, times(0)).executeUpdate("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (objectKey INTEGER, value TEXT, PRIMARY KEY (objectKey, value)) WITHOUT ROWID;"); }
@Test public void testInit_IndexTableDoesNotExist() throws Exception{ ConnectionManager connectionManager = mock(ConnectionManager.class); Connection connection = mock(Connection.class); Statement statement = mock(Statement.class); PreparedStatement preparedStatement = mock(PreparedStatement.class); java.sql.ResultSet tableCheckRs = mock(java.sql.ResultSet.class); java.sql.ResultSet journalModeRs = mock(java.sql.ResultSet.class); java.sql.ResultSet synchronousRs = mock(java.sql.ResultSet.class); when(tableCheckRs.next()).thenReturn(false); when(journalModeRs.next()).thenReturn(true).thenReturn(false); when(synchronousRs.next()).thenReturn(true).thenReturn(false); when(journalModeRs.getString(1)).thenReturn("DELETE"); when(synchronousRs.getInt(1)).thenReturn(2); when(statement.executeQuery("SELECT 1 FROM sqlite_master WHERE type='table' AND name='cqtbl_features';")).thenReturn(tableCheckRs); when(statement.executeQuery("PRAGMA journal_mode;")).thenReturn(journalModeRs); when(statement.executeQuery("PRAGMA synchronous;")).thenReturn(synchronousRs); when(connection.prepareStatement("INSERT OR IGNORE INTO " + TABLE_NAME + " values(?, ?);")).thenReturn(preparedStatement); when(connectionManager.getConnection(any(SQLiteIndex.class), anyQueryOptions())).thenReturn(connection); when(connectionManager.isApplyUpdateForIndexEnabled(any(SQLiteIndex.class))).thenReturn(true); when(connection.createStatement()).thenReturn(statement); when(preparedStatement.executeBatch()).thenReturn(new int[] {2}); Set<Car> initWithObjects = new HashSet<Car>(2); initWithObjects.add(new Car(1, "Ford", "Focus", Car.Color.BLUE, 5, 9000.50, Arrays.asList("abs", "gps"), Collections.emptyList())); initWithObjects.add(new Car(2, "Honda", "Civic", Car.Color.RED, 5, 5000.00, Arrays.asList("airbags"), Collections.emptyList())); SQLiteIndex<String, Car, Integer> carFeaturesOffHeapIndex = new SQLiteIndex<String, Car, Integer>( Car.FEATURES, OBJECT_TO_ID, ID_TO_OBJECT, "" ); carFeaturesOffHeapIndex.init(wrappingObjectStore(initWithObjects), createQueryOptions(connectionManager)); verify(statement, times(1)).executeQuery("PRAGMA journal_mode;"); verify(statement, times(1)).executeQuery("PRAGMA synchronous;"); verify(statement, times(1)).executeUpdate("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (objectKey INTEGER, value TEXT, PRIMARY KEY (objectKey, value)) WITHOUT ROWID;"); verify(statement, times(1)).executeUpdate("CREATE INDEX IF NOT EXISTS " + INDEX_NAME + " ON " + TABLE_NAME + " (value);"); verify(statement, times(6)).close(); verify(preparedStatement, times(2)).setObject(1, 1); verify(preparedStatement, times(1)).setObject(1, 2); verify(preparedStatement, times(1)).setObject(2, "abs"); verify(preparedStatement, times(1)).setObject(2, "gps"); verify(preparedStatement, times(1)).setObject(2, "airbags"); verify(preparedStatement, times(3)).addBatch(); verify(preparedStatement, times(1)).executeBatch(); verify(preparedStatement, times(1)).close(); verify(connection, times(0)).close(); Assert.assertEquals(carFeaturesOffHeapIndex.pragmaSynchronous, SQLiteConfig.SynchronousMode.FULL); Assert.assertEquals(carFeaturesOffHeapIndex.pragmaJournalMode, SQLiteConfig.JournalMode.DELETE); Assert.assertTrue(carFeaturesOffHeapIndex.canModifySyncAndJournaling); }