lib/sequel/plugins/many_through_many.rb in sequel-3.27.0 vs lib/sequel/plugins/many_through_many.rb in sequel-3.28.0
- old
+ new
@@ -56,10 +56,23 @@
# associations via eager.
def default_associated_key_alias
self[:uses_left_composite_keys] ? (0...self[:through].first[:left].length).map{|i| :"x_foreign_key_#{i}_x"} : :x_foreign_key_x
end
+ # The hash key to use for the eager loading predicate (left side of IN (1, 2, 3))
+ def eager_loading_predicate_key
+ self[:eager_loading_predicate_key] ||= begin
+ calculate_edges
+ e = self[:edges].first
+ if self[:uses_left_composite_keys]
+ e[:right].map{|k| SQL::QualifiedIdentifier.new(e[:table], k)}
+ else
+ SQL::QualifiedIdentifier.new(e[:table], e[:right])
+ end
+ end
+ end
+
# The list of joins to use when eager graphing
def edges
self[:edges] || calculate_edges || self[:edges]
end
@@ -180,23 +193,42 @@
end
left_key_alias = opts[:left_key_alias] ||= opts.default_associated_key_alias
opts[:eager_loader] ||= lambda do |eo|
h = eo[:key_hash][left_pk]
- eo[:rows].each{|object| object.associations[name] = []}
+ rows = eo[:rows]
+ rows.each{|object| object.associations[name] = []}
ds = opts.associated_class
opts.reverse_edges.each{|t| ds = ds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias])}
ft = opts[:final_reverse_edge]
conds = uses_lcks ? [[left_keys.map{|k| SQL::QualifiedIdentifier.new(ft[:table], k)}, h.keys]] : [[left_key, h.keys]]
ds = ds.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])) + conds, :table_alias=>ft[:alias])
- model.eager_loading_dataset(opts, ds, Array(opts.select), eo[:associations], eo).all do |assoc_record|
+ ds = model.eager_loading_dataset(opts, ds, Array(opts.select), eo[:associations], eo)
+ case opts.eager_limit_strategy
+ when :window_function
+ delete_rn = true
+ rn = ds.row_number_column
+ ds = apply_window_function_eager_limit_strategy(ds, opts)
+ when :correlated_subquery
+ ds = apply_correlated_subquery_eager_limit_strategy(ds, opts) do |xds|
+ dsa = ds.send(:dataset_alias, 2)
+ opts.reverse_edges.each{|t| xds = xds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias])}
+ xds.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])) + left_keys.map{|k| [k, SQL::QualifiedIdentifier.new(ft[:table], k)]}, :table_alias=>dsa)
+ end
+ end
+ ds.all do |assoc_record|
+ assoc_record.values.delete(rn) if delete_rn
hash_key = if uses_lcks
left_key_alias.map{|k| assoc_record.values.delete(k)}
else
assoc_record.values.delete(left_key_alias)
end
next unless objects = h[hash_key]
objects.each{|object| object.associations[name].push(assoc_record)}
+ end
+ if opts.eager_limit_strategy == :ruby
+ limit, offset = opts.limit_and_offset
+ rows.each{|o| o.associations[name] = o.associations[name].slice(offset||0, limit) || []}
end
end
join_type = opts[:graph_join_type]
select = opts[:graph_select]