23
23
import com .google .firebase .firestore .model .DocumentCollections ;
24
24
import com .google .firebase .firestore .model .DocumentKey ;
25
25
import com .google .firebase .firestore .model .MutableDocument ;
26
- import com .google .firebase .firestore .model .ResourcePath ;
27
26
import com .google .firebase .firestore .model .SnapshotVersion ;
28
27
import com .google .firebase .firestore .util .BackgroundQueue ;
29
28
import com .google .firebase .firestore .util .Executors ;
30
29
import com .google .protobuf .InvalidProtocolBufferException ;
31
30
import com .google .protobuf .MessageLite ;
32
31
import java .util .ArrayList ;
33
- import java .util .Collections ;
34
32
import java .util .HashMap ;
35
33
import java .util .List ;
36
34
import java .util .Map ;
@@ -64,10 +62,10 @@ public void add(MutableDocument document, SnapshotVersion readTime) {
64
62
65
63
db .execute (
66
64
"INSERT OR REPLACE INTO remote_documents "
67
- + "(collection_path, document_id , read_time_seconds, read_time_nanos, contents) "
65
+ + "(path, parent_path , read_time_seconds, read_time_nanos, contents) "
68
66
+ "VALUES (?, ?, ?, ?, ?)" ,
67
+ EncodedPath .encode (documentKey .getPath ()),
69
68
EncodedPath .encode (documentKey .getCollectionPath ()),
70
- documentKey .getPath ().getLastSegment (),
71
69
timestamp .getSeconds (),
72
70
timestamp .getNanoseconds (),
73
71
message .toByteArray ());
@@ -77,64 +75,53 @@ public void add(MutableDocument document, SnapshotVersion readTime) {
77
75
78
76
@ Override
79
77
public void remove (DocumentKey documentKey ) {
80
- db .execute (
81
- "DELETE FROM remote_documents WHERE collection_path = ? AND document_id = ?" ,
82
- EncodedPath .encode (documentKey .getCollectionPath ()),
83
- documentKey .getDocumentId ());
78
+ String path = EncodedPath .encode (documentKey .getPath ());
79
+
80
+ db .execute ("DELETE FROM remote_documents WHERE path = ?" , path );
84
81
}
85
82
86
83
@ Override
87
84
public MutableDocument get (DocumentKey documentKey ) {
85
+ String path = EncodedPath .encode (documentKey .getPath ());
86
+
88
87
MutableDocument document =
89
88
db .query (
90
- "SELECT contents, read_time_seconds, read_time_nanos FROM remote_documents "
91
- + "WHERE collection_path = ? AND document_id = ?" )
92
- .binding (
93
- EncodedPath .encode (documentKey .getCollectionPath ()), documentKey .getDocumentId ())
89
+ "SELECT contents, read_time_seconds, read_time_nanos "
90
+ + "FROM remote_documents WHERE path = ?" )
91
+ .binding (path )
94
92
.firstValue (row -> decodeMaybeDocument (row .getBlob (0 ), row .getInt (1 ), row .getInt (2 )));
95
93
return document != null ? document : MutableDocument .newInvalidDocument (documentKey );
96
94
}
97
95
98
96
@ Override
99
97
public Map <DocumentKey , MutableDocument > getAll (Iterable <DocumentKey > documentKeys ) {
100
98
Map <DocumentKey , MutableDocument > results = new HashMap <>();
101
-
102
- // We issue one query by collection, so first we have to sort the keys into collection buckets.
103
- Map <ResourcePath , List <Object >> collectionToDocumentIds = new HashMap <>();
99
+ List <Object > bindVars = new ArrayList <>();
104
100
for (DocumentKey key : documentKeys ) {
105
- ResourcePath path = key .getPath ();
106
- List <Object > documentIds = collectionToDocumentIds .get (path .popLast ());
107
- if (documentIds == null ) {
108
- documentIds = new ArrayList <>();
109
- collectionToDocumentIds .put (path .popLast (), documentIds );
110
- }
111
- documentIds .add (path .getLastSegment ());
101
+ bindVars .add (EncodedPath .encode (key .getPath ()));
112
102
113
103
// Make sure each key has a corresponding entry, which is null in case the document is not
114
104
// found.
115
105
results .put (key , MutableDocument .newInvalidDocument (key ));
116
106
}
117
107
118
- for (Map .Entry <ResourcePath , List <Object >> entry : collectionToDocumentIds .entrySet ()) {
119
- SQLitePersistence .LongQuery longQuery =
120
- new SQLitePersistence .LongQuery (
121
- db ,
122
- "SELECT contents, read_time_seconds, read_time_nanos FROM remote_documents "
123
- + "WHERE collection_path = ? AND document_id IN (" ,
124
- Collections .singletonList (EncodedPath .encode (entry .getKey ())),
125
- entry .getValue (),
126
- ")" );
127
-
128
- while (longQuery .hasMoreSubqueries ()) {
129
- longQuery
130
- .performNextSubquery ()
131
- .forEach (
132
- row -> {
133
- MutableDocument decoded =
134
- decodeMaybeDocument (row .getBlob (0 ), row .getInt (1 ), row .getInt (2 ));
135
- results .put (decoded .getKey (), decoded );
136
- });
137
- }
108
+ SQLitePersistence .LongQuery longQuery =
109
+ new SQLitePersistence .LongQuery (
110
+ db ,
111
+ "SELECT contents, read_time_seconds, read_time_nanos FROM remote_documents "
112
+ + "WHERE path IN (" ,
113
+ bindVars ,
114
+ ") ORDER BY path" );
115
+
116
+ while (longQuery .hasMoreSubqueries ()) {
117
+ longQuery
118
+ .performNextSubquery ()
119
+ .forEach (
120
+ row -> {
121
+ MutableDocument decoded =
122
+ decodeMaybeDocument (row .getBlob (0 ), row .getInt (1 ), row .getInt (2 ));
123
+ results .put (decoded .getKey (), decoded );
124
+ });
138
125
}
139
126
140
127
return results ;
@@ -147,7 +134,7 @@ public ImmutableSortedMap<DocumentKey, MutableDocument> getAllDocumentsMatchingQ
147
134
!query .isCollectionGroupQuery (),
148
135
"CollectionGroup queries should be handled in LocalDocumentsView" );
149
136
150
- String collectionPath = EncodedPath .encode (query .getPath ());
137
+ String parentPath = EncodedPath .encode (query .getPath ());
151
138
Timestamp readTime = sinceReadTime .getTimestamp ();
152
139
153
140
BackgroundQueue backgroundQueue = new BackgroundQueue ();
@@ -161,19 +148,19 @@ public ImmutableSortedMap<DocumentKey, MutableDocument> getAllDocumentsMatchingQ
161
148
sqlQuery =
162
149
db .query (
163
150
"SELECT contents, read_time_seconds, read_time_nanos "
164
- + "FROM remote_documents WHERE collection_path = ?" )
165
- .binding (collectionPath );
151
+ + "FROM remote_documents WHERE parent_path = ?" )
152
+ .binding (parentPath );
166
153
} else {
167
154
// Execute an index-free query and filter by read time. This is safe since all document
168
155
// changes to queries that have a lastLimboFreeSnapshotVersion (`sinceReadTime`) have a read
169
156
// time set.
170
157
sqlQuery =
171
158
db .query (
172
159
"SELECT contents, read_time_seconds, read_time_nanos "
173
- + "FROM remote_documents WHERE collection_path = ? "
160
+ + "FROM remote_documents WHERE parent_path = ? "
174
161
+ "AND (read_time_seconds > ? OR (read_time_seconds = ? AND read_time_nanos > ?))" )
175
162
.binding (
176
- collectionPath ,
163
+ parentPath ,
177
164
readTime .getSeconds (),
178
165
readTime .getSeconds (),
179
166
readTime .getNanoseconds ());
0 commit comments