@@ -227,7 +227,7 @@ def in_batches(of: 1000, start: nil, finish: nil, load: false, error_on_ignore:
227
227
batch_limit = remaining if remaining < batch_limit
228
228
end
229
229
230
- relation = relation . reorder ( batch_order ( order ) ) . limit ( batch_limit )
230
+ relation = relation . reorder ( * batch_order ( order ) ) . limit ( batch_limit )
231
231
relation = apply_limits ( relation , start , finish , order )
232
232
relation . skip_query_cache! # Retaining the results in the query cache would undermine the point of batching
233
233
batch_relation = relation
@@ -240,15 +240,15 @@ def in_batches(of: 1000, start: nil, finish: nil, load: false, error_on_ignore:
240
240
yielded_relation = where ( primary_key => ids )
241
241
yielded_relation . load_records ( records )
242
242
elsif ( empty_scope && use_ranges != false ) || use_ranges
243
- ids = batch_relation . pluck ( primary_key )
243
+ ids = batch_relation . ids
244
244
finish = ids . last
245
245
if finish
246
246
yielded_relation = apply_finish_limit ( batch_relation , finish , order )
247
247
yielded_relation = yielded_relation . except ( :limit , :order )
248
248
yielded_relation . skip_query_cache! ( false )
249
249
end
250
250
else
251
- ids = batch_relation . pluck ( primary_key )
251
+ ids = batch_relation . ids
252
252
yielded_relation = where ( primary_key => ids )
253
253
end
254
254
@@ -273,8 +273,8 @@ def in_batches(of: 1000, start: nil, finish: nil, load: false, error_on_ignore:
273
273
end
274
274
end
275
275
276
- batch_relation = relation . where (
277
- predicate_builder [ primary_key , primary_key_offset , order == :desc ? :lt : :gt ]
276
+ batch_relation = batch_condition (
277
+ relation , primary_key , primary_key_offset , order == :desc ? :lt : :gt
278
278
)
279
279
end
280
280
end
@@ -287,15 +287,32 @@ def apply_limits(relation, start, finish, order)
287
287
end
288
288
289
289
def apply_start_limit ( relation , start , order )
290
- relation . where ( predicate_builder [ primary_key , start , order == :desc ? :lteq : :gteq ] )
290
+ batch_condition ( relation , primary_key , start , order == :desc ? :lteq : :gteq )
291
291
end
292
292
293
293
def apply_finish_limit ( relation , finish , order )
294
- relation . where ( predicate_builder [ primary_key , finish , order == :desc ? :gteq : :lteq ] )
294
+ batch_condition ( relation , primary_key , finish , order == :desc ? :gteq : :lteq )
295
+ end
296
+
297
+ def batch_condition ( relation , columns , values , operator )
298
+ columns = Array ( columns )
299
+ values = Array ( values )
300
+ cursor_positions = columns . zip ( values )
301
+
302
+ first_clause_column , first_clause_value = cursor_positions . pop
303
+ where_clause = predicate_builder [ first_clause_column , first_clause_value , operator ]
304
+
305
+ cursor_positions . reverse_each do |column_name , value |
306
+ where_clause = predicate_builder [ column_name , value , operator == :lteq ? :lt : :gt ] . or (
307
+ predicate_builder [ column_name , value , :eq ] . and ( where_clause )
308
+ )
309
+ end
310
+
311
+ relation . where ( where_clause )
295
312
end
296
313
297
314
def batch_order ( order )
298
- table [ primary_key ] . public_send ( order )
315
+ Array ( primary_key ) . map { | column | table [ column ] . public_send ( order ) }
299
316
end
300
317
301
318
def act_on_ignored_order ( error_on_ignore )
0 commit comments