Skip to content

Commit

Permalink
fix: improve quey with duplicate alias (#687)
Browse files Browse the repository at this point in the history
close #512 

Co-authored-by: Nicolas Alexandre <[email protected]>
  • Loading branch information
matthv and nicolasalexandre9 authored Sep 10, 2024
1 parent 34600e1 commit a163407
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 157 deletions.
51 changes: 22 additions & 29 deletions app/services/forest_liana/base_getter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,14 @@ def get_collection(collection_name)
end

def get_resource
use_act_as_paranoid = @resource.instance_methods
.include? :really_destroyed?

# NOTICE: Do not unscope with the paranoia gem to prevent the retrieval
# of deleted records.
use_act_as_paranoid ? @resource : @resource.unscoped
@resource.instance_methods.include?(:really_destroyed?) ? @resource : @resource.unscoped
end

def includes_for_serialization
includes_initial = @includes
includes_for_smart_belongs_to = @collection.fields_smart_belongs_to.map { |field| field[:field] }
includes_for_smart_belongs_to &= @field_names_requested if @field_names_requested

if @field_names_requested
includes_for_smart_belongs_to = includes_for_smart_belongs_to & @field_names_requested
end

includes_initial.concat(includes_for_smart_belongs_to).map(&:to_s)
@includes.concat(includes_for_smart_belongs_to).map(&:to_s)
end

private
Expand All @@ -31,34 +22,36 @@ def compute_includes
end

def optimize_record_loading(resource, records)
instance_dependent_associations = instance_dependent_associations(resource)
polymorphic, preload_loads = analyze_associations(resource)
result = records.eager_load(@includes.uniq - preload_loads - polymorphic)

result = result.preload(preload_loads) if Rails::VERSION::MAJOR >= 7

result
end

def analyze_associations(resource)
polymorphic = []
preload_loads = @includes.select do |name|
preload_loads = @includes.uniq.select do |name|
association = resource.reflect_on_association(name)
if SchemaUtils.polymorphic?(association)
polymorphic << association.name
false
else
targetModelConnection = association.klass.connection
targetModelDatabase = targetModelConnection.current_database if targetModelConnection.respond_to? :current_database
resourceConnection = resource.connection
resourceDatabase = resourceConnection.current_database if resourceConnection.respond_to? :current_database

targetModelDatabase != resourceDatabase
separate_database?(resource, association)
end
end + instance_dependent_associations
end + instance_dependent_associations(resource)

result = records.eager_load(@includes - preload_loads - polymorphic)
[polymorphic, preload_loads]
end

# Rails 7 can mix `eager_load` and `preload` in the same scope
# Rails 6 cannot mix `eager_load` and `preload` in the same scope
# Rails 6 and 7 cannot mix `eager_load` and `includes` in the same scope
if Rails::VERSION::MAJOR >= 7
result = result.preload(preload_loads)
end
def separate_database?(resource, association)
target_model_connection = association.klass.connection
target_model_database = target_model_connection.current_database if target_model_connection.respond_to? :current_database
resource_connection = resource.connection
resource_database = resource_connection.current_database if resource_connection.respond_to? :current_database

result
target_model_database != resource_database
end

def instance_dependent_associations(resource)
Expand Down
18 changes: 7 additions & 11 deletions app/services/forest_liana/filters_parser.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module ForestLiana
class FiltersParser
AGGREGATOR_OPERATOR = %w(and or)
AGGREGATOR_OPERATOR = %w(and or).freeze

def initialize(filters, resource, timezone, params = nil)
@filters = filters
Expand All @@ -13,18 +13,14 @@ def initialize(filters, resource, timezone, params = nil)
def apply_filters
return @resource unless @filters

where = parse_aggregation(@filters)
return @resource unless where
where_clause = parse_aggregation(@filters)
return @resource unless where_clause

@joins.each do |join|
current_resource = @resource.reflect_on_association(join.name).klass
current_resource.include(ArelHelpers::Aliases)
current_resource.aliased_as(join.name) do |aliased_resource|
@resource = @resource.joins(ArelHelpers.join_association(@resource, join.name, Arel::Nodes::OuterJoin, aliases: [aliased_resource]))
end
@resource = @resource.eager_load(join.name)
end

@resource.where(where)
@resource.where(where_clause)
end

def parse_aggregation(node)
Expand Down Expand Up @@ -170,8 +166,8 @@ def parse_field_name(field)
current_resource = @resource.reflect_on_association(field.split(':').first.to_sym)&.klass
raise ForestLiana::Errors::HTTP422Error.new("Field '#{field}' not found") unless current_resource

association = get_association_name_for_condition(field)
quoted_table_name = ActiveRecord::Base.connection.quote_column_name(association)
get_association_name_for_condition(field)
quoted_table_name = current_resource.table_name
field_name = field.split(':')[1]
else
quoted_table_name = @resource.quoted_table_name
Expand Down
Loading

0 comments on commit a163407

Please sign in to comment.