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]