@@ -190,59 +190,73 @@ public Set<DocumentKey> getDocumentsMatchingTarget(Target target) {
190
190
}
191
191
192
192
Set <DocumentKey > result = new HashSet <>();
193
- BindArgs bindArgs ;
193
+ SQLitePersistence . Query query ;
194
194
195
195
Object [] lowerBoundValues = encodeTargetValues (fieldIndex , target , lowerBound .getPosition ());
196
196
String lowerBoundOp = lowerBound .isBefore () ? ">=" : ">" ; // `startAt()` versus `startAfter()`
197
197
if (upperBound != null ) {
198
198
Object [] upperBoundValues = encodeTargetValues (fieldIndex , target , upperBound .getPosition ());
199
199
String upperBoundOp = upperBound .isBefore () ? "<" : "<=" ; // `endBefore()` versus `endAt()`
200
- bindArgs = generateBindArgs (lowerBoundValues , lowerBoundOp , upperBoundValues , upperBoundOp );
200
+ query =
201
+ generateQuery (
202
+ fieldIndex .getIndexId (),
203
+ lowerBoundValues ,
204
+ lowerBoundOp ,
205
+ upperBoundValues ,
206
+ upperBoundOp );
201
207
} else {
202
- bindArgs = generateBindArgs ( lowerBoundValues , lowerBoundOp );
208
+ query = generateQuery ( fieldIndex . getIndexId (), lowerBoundValues , lowerBoundOp );
203
209
}
204
210
205
- String sql =
206
- String .format (
207
- "SELECT document_name from index_entries WHERE index_id = %s AND (%s)" ,
208
- fieldIndex .getIndexId (), bindArgs .sql );
209
- db .query (sql )
210
- .binding (bindArgs .bindArgs )
211
- .forEach (
212
- row -> result .add (DocumentKey .fromPath (ResourcePath .fromString (row .getString (0 )))));
211
+ query .forEach (
212
+ row -> result .add (DocumentKey .fromPath (ResourcePath .fromString (row .getString (0 )))));
213
213
214
214
// TODO(indexing): Add limit handling
215
215
216
216
Logger .debug (TAG , "Index scan returned %s documents" , result .size ());
217
217
return result ;
218
218
}
219
219
220
- /** Returns a SQL filter that concatenates all {@code value} into a disjunction. */
221
- private BindArgs generateBindArgs (Object [] values , String op ) {
222
- String [] filters = new String [values .length ];
223
- for (int i = 0 ; i < values .length ; ++i ) {
224
- filters [i ] = String .format ("index_value %s ?" , op );
220
+ /** Returns a SQL query on 'index_entries' that unions all bounds. */
221
+ private SQLitePersistence .Query generateQuery (int indexId , Object [] bounds , String op ) {
222
+ String [] statements = new String [bounds .length ];
223
+ Object [] bingArgs = new Object [bounds .length * 2 ];
224
+ for (int i = 0 ; i < bounds .length ; ++i ) {
225
+ statements [i ] =
226
+ String .format (
227
+ "SELECT document_name FROM index_entries WHERE index_id = ? AND index_value %s ?" ,
228
+ op );
229
+ bingArgs [i * 2 ] = indexId ;
230
+ bingArgs [i * 2 + 1 ] = bounds [i ];
225
231
}
226
- return new BindArgs (TextUtils .join (" OR " , filters ), values );
232
+ String sql = TextUtils .join (" UNION " , statements );
233
+ return db .query (sql ).binding (bingArgs );
227
234
}
228
235
229
- /**
230
- * Returns a SQL filter that combines each element from the left list with each element from the
231
- * right list and returns all combinations (e.g. `(left1 AND right1) OR (left1 AND right2) ...`).
232
- */
233
- private BindArgs generateBindArgs (Object [] left , String leftOp , Object [] right , String rightOp ) {
234
- String [] filters = new String [left .length * right .length ];
235
- Object [] bingArgs = new Object [left .length * right .length * 2 ];
236
+ /** Returns a SQL query on 'index_entries' that unions all bounds. */
237
+ private SQLitePersistence .Query generateQuery (
238
+ int indexId ,
239
+ Object [] lowerBounds ,
240
+ String lowerBoundOp ,
241
+ Object [] upperBounds ,
242
+ String upperBoundOp ) {
243
+ String [] statements = new String [lowerBounds .length * upperBounds .length ];
244
+ Object [] bingArgs = new Object [lowerBounds .length * upperBounds .length * 3 ];
236
245
int i = 0 ;
237
- for (Object value1 : left ) {
238
- for (Object value2 : right ) {
239
- filters [i ] = String .format ("index_value %s ? AND index_value %s ?" , leftOp , rightOp );
240
- bingArgs [i * 2 ] = value1 ;
241
- bingArgs [i * 2 + 1 ] = value2 ;
246
+ for (Object value1 : lowerBounds ) {
247
+ for (Object value2 : upperBounds ) {
248
+ statements [i ] =
249
+ String .format (
250
+ "SELECT document_name FROM index_entries WHERE index_id = ? AND index_value %s ? AND index_value %s ?" ,
251
+ lowerBoundOp , upperBoundOp );
252
+ bingArgs [i * 3 ] = indexId ;
253
+ bingArgs [i * 3 + 1 ] = value1 ;
254
+ bingArgs [i * 3 + 2 ] = value2 ;
242
255
++i ;
243
256
}
244
257
}
245
- return new BindArgs (TextUtils .join (" OR " , filters ), bingArgs );
258
+ String sql = TextUtils .join (" UNION " , statements );
259
+ return db .query (sql ).binding (bingArgs );
246
260
}
247
261
248
262
/**
@@ -378,15 +392,4 @@ private boolean isMultiValueFilter(Target target, FieldPath fieldPath) {
378
392
private byte [] encodeFieldIndex (FieldIndex fieldIndex ) {
379
393
return serializer .encodeFieldIndex (fieldIndex ).toByteArray ();
380
394
}
381
-
382
- /** Stores a SQL statement of filters and their corresponding bind arguments. */
383
- static class BindArgs {
384
- final String sql ;
385
- final Object [] bindArgs ;
386
-
387
- BindArgs (String sql , Object [] bindArgs ) {
388
- this .sql = sql ;
389
- this .bindArgs = bindArgs ;
390
- }
391
- }
392
395
}
0 commit comments