@@ -59,6 +59,20 @@ use crate::{
59
59
#[ cfg( any( feature = "full" , feature = "verify" ) ) ]
60
60
use crate :: { Element , SizedQuery } ;
61
61
62
+ #[ cfg( feature = "full" ) ]
63
+ #[ derive( Copy , Clone , Debug ) ]
64
+ pub struct QueryOptions {
65
+ pub allow_get_raw : bool ,
66
+ pub allow_cache : bool ,
67
+ /// Should we decrease the limit of elements found when we have no
68
+ /// subelements in the subquery? This should generally be set to true,
69
+ /// as having it false could mean very expensive queries. The queries
70
+ /// would be expensive because we could go through many many trees where the
71
+ /// sub elements have no matches, hence the limit would not decrease and
72
+ /// hence we would continue on the increasingly expensive query.
73
+ pub decrease_limit_on_range_with_no_sub_elements : bool ,
74
+ }
75
+
62
76
#[ cfg( feature = "full" ) ]
63
77
/// Path query push arguments
64
78
pub struct PathQueryPushArgs < ' db , ' ctx , ' a >
73
87
pub subquery_path : Option < Path > ,
74
88
pub subquery : Option < Query > ,
75
89
pub left_to_right : bool ,
76
- pub allow_get_raw : bool ,
77
- pub allow_cache : bool ,
90
+ pub query_options : QueryOptions ,
78
91
pub result_type : QueryResultType ,
79
92
pub results : & ' a mut Vec < QueryResultElement > ,
80
93
pub limit : & ' a mut Option < u16 > ,
@@ -97,6 +110,7 @@ impl Element {
97
110
merk_path,
98
111
& sized_query,
99
112
true ,
113
+ true ,
100
114
result_type,
101
115
transaction,
102
116
)
@@ -139,8 +153,7 @@ impl Element {
139
153
storage : & RocksDbStorage ,
140
154
path : & [ & [ u8 ] ] ,
141
155
sized_query : & SizedQuery ,
142
- allow_get_raw : bool ,
143
- allow_cache : bool ,
156
+ query_options : QueryOptions ,
144
157
result_type : QueryResultType ,
145
158
transaction : TransactionArg ,
146
159
add_element_function : fn ( PathQueryPushArgs ) -> CostResult < ( ) , Error > ,
@@ -166,8 +179,7 @@ impl Element {
166
179
transaction,
167
180
& mut limit,
168
181
& mut offset,
169
- allow_get_raw,
170
- allow_cache,
182
+ query_options,
171
183
result_type,
172
184
add_element_function,
173
185
)
@@ -189,8 +201,7 @@ impl Element {
189
201
transaction,
190
202
& mut limit,
191
203
& mut offset,
192
- allow_get_raw,
193
- allow_cache,
204
+ query_options,
194
205
result_type,
195
206
add_element_function,
196
207
)
@@ -216,6 +227,7 @@ impl Element {
216
227
storage : & RocksDbStorage ,
217
228
path_query : & PathQuery ,
218
229
allow_cache : bool ,
230
+ decrease_limit_on_range_with_no_sub_elements : bool ,
219
231
result_type : QueryResultType ,
220
232
transaction : TransactionArg ,
221
233
) -> CostResult < ( QueryResultElements , u16 ) , Error > {
@@ -228,8 +240,11 @@ impl Element {
228
240
storage,
229
241
path_slices. as_slice ( ) ,
230
242
& path_query. query ,
231
- false ,
232
- allow_cache,
243
+ QueryOptions {
244
+ allow_get_raw : false ,
245
+ allow_cache,
246
+ decrease_limit_on_range_with_no_sub_elements,
247
+ } ,
233
248
result_type,
234
249
transaction,
235
250
Element :: path_query_push,
@@ -243,6 +258,7 @@ impl Element {
243
258
storage : & RocksDbStorage ,
244
259
path_query : & PathQuery ,
245
260
allow_cache : bool ,
261
+ decrease_limit_on_range_with_no_sub_elements : bool ,
246
262
result_type : QueryResultType ,
247
263
transaction : TransactionArg ,
248
264
) -> CostResult < ( QueryResultElements , u16 ) , Error > {
@@ -255,8 +271,11 @@ impl Element {
255
271
storage,
256
272
path_slices. as_slice ( ) ,
257
273
& path_query. query ,
258
- true ,
259
- allow_cache,
274
+ QueryOptions {
275
+ allow_get_raw : true ,
276
+ allow_cache,
277
+ decrease_limit_on_range_with_no_sub_elements,
278
+ } ,
260
279
result_type,
261
280
transaction,
262
281
Element :: path_query_push,
@@ -270,15 +289,19 @@ impl Element {
270
289
path : & [ & [ u8 ] ] ,
271
290
sized_query : & SizedQuery ,
272
291
allow_cache : bool ,
292
+ decrease_limit_on_range_with_no_sub_elements : bool ,
273
293
result_type : QueryResultType ,
274
294
transaction : TransactionArg ,
275
295
) -> CostResult < ( QueryResultElements , u16 ) , Error > {
276
296
Element :: get_query_apply_function (
277
297
storage,
278
298
path,
279
299
sized_query,
280
- false ,
281
- allow_cache,
300
+ QueryOptions {
301
+ allow_get_raw : false ,
302
+ allow_cache,
303
+ decrease_limit_on_range_with_no_sub_elements,
304
+ } ,
282
305
result_type,
283
306
transaction,
284
307
Element :: path_query_push,
@@ -299,13 +322,17 @@ impl Element {
299
322
subquery_path,
300
323
subquery,
301
324
left_to_right,
302
- allow_get_raw,
303
- allow_cache,
325
+ query_options,
304
326
result_type,
305
327
results,
306
328
limit,
307
329
offset,
308
330
} = args;
331
+ let QueryOptions {
332
+ allow_get_raw,
333
+ allow_cache,
334
+ decrease_limit_on_range_with_no_sub_elements,
335
+ } = query_options;
309
336
if element. is_tree ( ) {
310
337
let mut path_vec = path. to_vec ( ) ;
311
338
let key = cost_return_on_error_no_add ! (
@@ -331,13 +358,19 @@ impl Element {
331
358
storage,
332
359
& inner_path_query,
333
360
allow_cache,
361
+ decrease_limit_on_range_with_no_sub_elements,
334
362
result_type,
335
363
transaction
336
364
)
337
365
) ;
338
366
339
367
if let Some ( limit) = limit {
340
- * limit = limit. saturating_sub ( sub_elements. len ( ) as u16 ) ;
368
+ if sub_elements. is_empty ( ) && decrease_limit_on_range_with_no_sub_elements {
369
+ // we should decrease by 1 in this case
370
+ * limit = limit. saturating_sub ( 1 ) ;
371
+ } else {
372
+ * limit = limit. saturating_sub ( sub_elements. len ( ) as u16 ) ;
373
+ }
341
374
}
342
375
if let Some ( offset) = offset {
343
376
* offset = offset. saturating_sub ( skipped) ;
@@ -455,8 +488,7 @@ impl Element {
455
488
subquery_path,
456
489
subquery,
457
490
left_to_right,
458
- allow_get_raw,
459
- allow_cache,
491
+ query_options,
460
492
result_type,
461
493
results,
462
494
limit,
@@ -483,8 +515,7 @@ impl Element {
483
515
subquery_path,
484
516
subquery,
485
517
left_to_right,
486
- allow_get_raw,
487
- allow_cache,
518
+ query_options,
488
519
result_type,
489
520
results,
490
521
limit,
@@ -530,6 +561,12 @@ impl Element {
530
561
( subquery_path, subquery)
531
562
}
532
563
564
+ /// `decrease_limit_on_range_with_no_sub_elements` should generally be set
565
+ /// to true, as having it false could mean very expensive queries.
566
+ /// The queries would be expensive because we could go through many many
567
+ /// trees where the sub elements have no matches, hence the limit would
568
+ /// not decrease and hence we would continue on the increasingly
569
+ /// expensive query.
533
570
#[ cfg( feature = "full" ) ]
534
571
// TODO: refactor
535
572
fn query_item (
@@ -541,8 +578,7 @@ impl Element {
541
578
transaction : TransactionArg ,
542
579
limit : & mut Option < u16 > ,
543
580
offset : & mut Option < u16 > ,
544
- allow_get_raw : bool ,
545
- allow_cache : bool ,
581
+ query_options : QueryOptions ,
546
582
result_type : QueryResultType ,
547
583
add_element_function : fn ( PathQueryPushArgs ) -> CostResult < ( ) , Error > ,
548
584
) -> CostResult < ( ) , Error > {
@@ -560,7 +596,10 @@ impl Element {
560
596
None ,
561
597
transaction,
562
598
subtree,
563
- { Element :: get( & subtree, key, allow_cache) . unwrap_add_cost( & mut cost) }
599
+ {
600
+ Element :: get( & subtree, key, query_options. allow_cache)
601
+ . unwrap_add_cost( & mut cost)
602
+ }
564
603
) ;
565
604
match element_res {
566
605
Ok ( element) => {
@@ -575,8 +614,7 @@ impl Element {
575
614
subquery_path,
576
615
subquery,
577
616
left_to_right : sized_query. query . left_to_right ,
578
- allow_get_raw,
579
- allow_cache,
617
+ query_options,
580
618
result_type,
581
619
results,
582
620
limit,
@@ -630,8 +668,7 @@ impl Element {
630
668
subquery_path,
631
669
subquery,
632
670
left_to_right: sized_query. query. left_to_right,
633
- allow_get_raw,
634
- allow_cache,
671
+ query_options,
635
672
result_type,
636
673
results,
637
674
limit,
@@ -939,6 +976,7 @@ mod tests {
939
976
& [ TEST_LEAF ] ,
940
977
& ascending_query,
941
978
true ,
979
+ true ,
942
980
QueryKeyElementPairResultType ,
943
981
None ,
944
982
)
@@ -973,6 +1011,7 @@ mod tests {
973
1011
& [ TEST_LEAF ] ,
974
1012
& backwards_query,
975
1013
true ,
1014
+ true ,
976
1015
QueryKeyElementPairResultType ,
977
1016
None ,
978
1017
)
@@ -1062,6 +1101,7 @@ mod tests {
1062
1101
& [ TEST_LEAF ] ,
1063
1102
& ascending_query,
1064
1103
true ,
1104
+ true ,
1065
1105
QueryKeyElementPairResultType ,
1066
1106
None ,
1067
1107
)
@@ -1079,6 +1119,7 @@ mod tests {
1079
1119
& [ TEST_LEAF ] ,
1080
1120
& backwards_query,
1081
1121
true ,
1122
+ true ,
1082
1123
QueryKeyElementPairResultType ,
1083
1124
None ,
1084
1125
)
@@ -1099,6 +1140,7 @@ mod tests {
1099
1140
& [ TEST_LEAF ] ,
1100
1141
& backwards_query,
1101
1142
true ,
1143
+ true ,
1102
1144
QueryKeyElementPairResultType ,
1103
1145
None ,
1104
1146
)
@@ -1161,6 +1203,7 @@ mod tests {
1161
1203
& [ TEST_LEAF ] ,
1162
1204
& backwards_query,
1163
1205
true ,
1206
+ true ,
1164
1207
QueryKeyElementPairResultType ,
1165
1208
None ,
1166
1209
)
@@ -1187,6 +1230,7 @@ mod tests {
1187
1230
& [ TEST_LEAF ] ,
1188
1231
& backwards_query,
1189
1232
true ,
1233
+ true ,
1190
1234
QueryKeyElementPairResultType ,
1191
1235
None ,
1192
1236
)
@@ -1208,6 +1252,7 @@ mod tests {
1208
1252
& [ TEST_LEAF ] ,
1209
1253
& limit_query,
1210
1254
true ,
1255
+ true ,
1211
1256
QueryKeyElementPairResultType ,
1212
1257
None ,
1213
1258
)
@@ -1229,6 +1274,7 @@ mod tests {
1229
1274
& [ TEST_LEAF ] ,
1230
1275
& limit_query,
1231
1276
true ,
1277
+ true ,
1232
1278
QueryKeyElementPairResultType ,
1233
1279
None ,
1234
1280
)
@@ -1249,6 +1295,7 @@ mod tests {
1249
1295
& [ TEST_LEAF ] ,
1250
1296
& limit_offset_query,
1251
1297
true ,
1298
+ true ,
1252
1299
QueryKeyElementPairResultType ,
1253
1300
None ,
1254
1301
)
@@ -1274,6 +1321,7 @@ mod tests {
1274
1321
& [ TEST_LEAF ] ,
1275
1322
& limit_offset_backwards_query,
1276
1323
true ,
1324
+ true ,
1277
1325
QueryKeyElementPairResultType ,
1278
1326
None ,
1279
1327
)
@@ -1298,6 +1346,7 @@ mod tests {
1298
1346
& [ TEST_LEAF ] ,
1299
1347
& limit_full_query,
1300
1348
true ,
1349
+ true ,
1301
1350
QueryKeyElementPairResultType ,
1302
1351
None ,
1303
1352
)
@@ -1323,6 +1372,7 @@ mod tests {
1323
1372
& [ TEST_LEAF ] ,
1324
1373
& limit_offset_backwards_query,
1325
1374
true ,
1375
+ true ,
1326
1376
QueryKeyElementPairResultType ,
1327
1377
None ,
1328
1378
)
@@ -1348,6 +1398,7 @@ mod tests {
1348
1398
& [ TEST_LEAF ] ,
1349
1399
& limit_backwards_query,
1350
1400
true ,
1401
+ true ,
1351
1402
QueryKeyElementPairResultType ,
1352
1403
None ,
1353
1404
)
0 commit comments