Skip to content

Commit 1ae24a5

Browse files
Add SimpleQueryEngine
1 parent 2fef555 commit 1ae24a5

File tree

6 files changed

+114
-4
lines changed

6 files changed

+114
-4
lines changed

packages/firestore/src/core/firestore_client.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { IndexedDbPersistence } from '../local/indexeddb_persistence';
2121
import { LocalStore } from '../local/local_store';
2222
import { MemoryPersistence } from '../local/memory_persistence';
2323
import { Persistence } from '../local/persistence';
24+
import { SimpleQueryEngine } from '../local/simple_query_engine';
2425
import {
2526
DocumentKeySet,
2627
documentKeySet,
@@ -406,7 +407,9 @@ export class FirestoreClient {
406407
return this.platform
407408
.loadConnection(this.databaseInfo)
408409
.then(async connection => {
409-
this.localStore = new LocalStore(this.persistence, user);
410+
// TODO(index-free): Use IndexFreeQueryEngine/IndexedQueryEngine as appropriate.
411+
const queryEngine = new SimpleQueryEngine();
412+
this.localStore = new LocalStore(this.persistence, queryEngine, user);
410413
if (maybeLruGc) {
411414
// We're running LRU Garbage collection. Set up the scheduler.
412415
this.lruScheduler = new LruScheduler(

packages/firestore/src/local/local_store.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { Persistence, PersistenceTransaction } from './persistence';
4848
import { PersistencePromise } from './persistence_promise';
4949
import { QueryCache } from './query_cache';
5050
import { QueryData, QueryPurpose } from './query_data';
51+
import { QueryEngine } from './query_engine';
5152
import { ReferenceSet } from './reference_set';
5253
import { RemoteDocumentCache } from './remote_document_cache';
5354
import { RemoteDocumentChangeBuffer } from './remote_document_change_buffer';
@@ -158,6 +159,7 @@ export class LocalStore {
158159
constructor(
159160
/** Manages our in-memory or durable persistence. */
160161
private persistence: Persistence,
162+
private queryEngine: QueryEngine,
161163
initialUser: User
162164
) {
163165
assert(
@@ -175,6 +177,7 @@ export class LocalStore {
175177
this.mutationQueue,
176178
this.persistence.getIndexManager()
177179
);
180+
this.queryEngine.setLocalDocumentsView(this.localDocuments);
178181
}
179182

180183
/**
@@ -819,7 +822,7 @@ export class LocalStore {
819822
*/
820823
executeQuery(query: Query): Promise<DocumentMap> {
821824
return this.persistence.runTransaction('Execute query', 'readonly', txn => {
822-
return this.localDocuments.getDocumentsMatchingQuery(
825+
return this.queryEngine.getDocumentsMatchingQuery(
823826
txn,
824827
query,
825828
SnapshotVersion.MIN
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { LocalDocumentsView } from './local_documents_view';
19+
import { PersistenceTransaction } from './persistence';
20+
import { Query } from '../core/query';
21+
import { SnapshotVersion } from '../core/snapshot_version';
22+
import { PersistencePromise } from './persistence_promise';
23+
import { DocumentMap } from '../model/collections';
24+
25+
/**
26+
* Represents a query engine capable of performing queries over the local
27+
* document cache. You must call `setLocalDocumentsView()` before using.
28+
*/
29+
export interface QueryEngine {
30+
/** Sets the document view to query against. */
31+
setLocalDocumentsView(localDocuments: LocalDocumentsView): void;
32+
33+
/** Returns all local documents matching the specified query. */
34+
getDocumentsMatchingQuery(
35+
transaction: PersistenceTransaction,
36+
query: Query,
37+
sinceReadTime: SnapshotVersion
38+
): PersistencePromise<DocumentMap>;
39+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { LocalDocumentsView } from './local_documents_view';
19+
import { PersistenceTransaction } from './persistence';
20+
import { Query } from '../core/query';
21+
import { SnapshotVersion } from '../core/snapshot_version';
22+
import { PersistencePromise } from './persistence_promise';
23+
import { DocumentMap } from '../model/collections';
24+
import { QueryEngine } from './query_engine';
25+
import { assert } from '../util/assert';
26+
27+
/**
28+
* A naive implementation of QueryEngine that just loads all the documents in
29+
* the queried collection and then filters them in memory.
30+
*/
31+
export class SimpleQueryEngine implements QueryEngine {
32+
private localDocumentsView: LocalDocumentsView | undefined;
33+
34+
setLocalDocumentsView(localDocuments: LocalDocumentsView): void {
35+
this.localDocumentsView = localDocuments;
36+
}
37+
38+
/** Returns all local documents matching the specified query. */
39+
getDocumentsMatchingQuery(
40+
transaction: PersistenceTransaction,
41+
query: Query,
42+
sinceReadTime: SnapshotVersion
43+
): PersistencePromise<DocumentMap> {
44+
assert(
45+
this.localDocumentsView !== undefined,
46+
'setLocalDocumentsView() not called'
47+
);
48+
49+
// TODO: Once LocalDocumentsView provides a getCollectionDocuments()
50+
// method, we should call that here and then filter the results.
51+
return this.localDocumentsView!.getDocumentsMatchingQuery(
52+
transaction,
53+
query,
54+
SnapshotVersion.MIN
55+
);
56+
}
57+
}

packages/firestore/test/unit/local/local_store.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
2525
import { LocalStore, LocalWriteResult } from '../../../src/local/local_store';
2626
import { LocalViewChanges } from '../../../src/local/local_view_changes';
2727
import { Persistence } from '../../../src/local/persistence';
28+
import { QueryEngine } from '../../../src/local/query_engine';
29+
import { SimpleQueryEngine } from '../../../src/local/simple_query_engine';
2830
import {
2931
documentKeySet,
3032
DocumentMap,
@@ -280,6 +282,7 @@ describe('LocalStore w/ Memory Persistence', () => {
280282
addEqualityMatcher();
281283
genericLocalStoreTests(
282284
persistenceHelpers.testMemoryEagerPersistence,
285+
new SimpleQueryEngine(),
283286
/* gcIsEager= */ true
284287
);
285288
});
@@ -295,20 +298,22 @@ describe('LocalStore w/ IndexedDB Persistence', () => {
295298
addEqualityMatcher();
296299
genericLocalStoreTests(
297300
persistenceHelpers.testIndexedDbPersistence,
301+
new SimpleQueryEngine(),
298302
/* gcIsEager= */ false
299303
);
300304
});
301305

302306
function genericLocalStoreTests(
303307
getPersistence: () => Promise<Persistence>,
308+
queryEngine: QueryEngine,
304309
gcIsEager: boolean
305310
): void {
306311
let persistence: Persistence;
307312
let localStore: LocalStore;
308313

309314
beforeEach(async () => {
310315
persistence = await getPersistence();
311-
localStore = new LocalStore(persistence, User.UNAUTHENTICATED);
316+
localStore = new LocalStore(persistence, queryEngine, User.UNAUTHENTICATED);
312317
});
313318

314319
afterEach(async () => {

packages/firestore/test/unit/specs/spec_test_runner.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import {
5757
WebStorageSharedClientState
5858
} from '../../../src/local/shared_client_state';
5959
import { SimpleDb } from '../../../src/local/simple_db';
60+
import { SimpleQueryEngine } from '../../../src/local/simple_query_engine';
6061
import { DocumentOptions } from '../../../src/model/document';
6162
import { DocumentKey } from '../../../src/model/document_key';
6263
import { JsonObject } from '../../../src/model/field_value';
@@ -434,7 +435,9 @@ abstract class TestRunner {
434435
this.useGarbageCollection
435436
);
436437

437-
this.localStore = new LocalStore(this.persistence, this.user);
438+
// TODO(index-free): Update to index-free query engine when it becomes default.
439+
const queryEngine = new SimpleQueryEngine();
440+
this.localStore = new LocalStore(this.persistence, queryEngine, this.user);
438441

439442
this.connection = new MockConnection(this.queue);
440443
this.datastore = new Datastore(

0 commit comments

Comments
 (0)