Skip to content

Commit

Permalink
fix compile time error with impossible relation typecasting in mqrt
Browse files Browse the repository at this point in the history
  • Loading branch information
imdrasil committed Jul 5, 2018
1 parent f67189b commit 0483bf9
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 78 deletions.
8 changes: 8 additions & 0 deletions spec/query_builder/model_query_spec.cr
Expand Up @@ -663,6 +663,14 @@ describe Jennifer::QueryBuilder::ModelQuery do
.order({"period" => :desc})
.results.size.should eq(1)
end

it "allows to use float for filtering decimal fields" do
converter = Jennifer::Model::ParameterConverter.new
c = Factory.create_contact
c.ballance = converter.parse("15.1", "Numeric").as(PG::Numeric)
c.save
Contact.all.where { _ballance == 15.1 }.count.should eq(1)
end
end
end
end
4 changes: 4 additions & 0 deletions src/jennifer.cr
Expand Up @@ -68,6 +68,10 @@ module Jennifer
raise "stubed relation"
end

def preload_relation(collection, out_collection, pk_repo)
raise "stubbed relation"
end

{% for method in %i(table_name model_class type set_callback condition_clause foreign_field primary_field join_query) %}
def {{method.id}}
raise "stubed relation"
Expand Down
79 changes: 1 addition & 78 deletions src/jennifer/query_builder/multi_query_relation_tree.cr
Expand Up @@ -20,84 +20,7 @@ module Jennifer
(@bucket.size + 1).times { |_| pk_repo << {} of DBAny => Array(DBAny) }

@bucket.each_with_index do |pair, index|
preload_relation(repo[pair[0]], repo[index + 1].as(Array(Model::Resource)), pair[1], pk_repo[index])
end
end

private def preload_relation(collection, out_collection : Array(Model::Resource), relation : Relation::ManyToMany, pk_repo)
return if collection.empty?
_primary = relation.primary_field
_foreign = relation.foreign_field

unless pk_repo.has_key?(_primary)
array = pk_repo[_primary] = Array(DBAny).new(collection.size)
collection.each { |e| array << e.attribute(_primary) }
end

join_fk = "__join_fk__"
query = relation.query(pk_repo[_primary])
fields = query._select_fields
fields << Criteria.new(_foreign, relation.join_table!).alias(join_fk)
new_collection = query.select(fields).db_results

name = relation.name
if new_collection.empty?
collection.each(&.relation_retrieved(name))
else
primary_fields = pk_repo[_primary]
collection.each_with_index do |mod, i|
pv = primary_fields[i]
new_collection.each { |hash| out_collection << mod.append_relation(name, hash) if hash[join_fk] == pv }
end
end
end

private def preload_relation(collection, out_collection : Array(Model::Resource), relation : Relation::BelongsTo, pk_repo)
return if collection.empty?
_primary = relation.primary_field
_foreign = relation.foreign_field

unless pk_repo.has_key?(_foreign)
array = pk_repo[_foreign] = Array(DBAny).new(collection.size)
collection.each { |e| array << e.attribute(_foreign) }
end

new_collection = relation.query(pk_repo[_foreign]).db_results

name = relation.name
if new_collection.empty?
collection.each(&.relation_retrieved(name))
else
foreign_fields = pk_repo[_foreign]
collection.each_with_index do |mod, i|
fk = foreign_fields[i]
new_collection.each { |hash| out_collection << mod.append_relation(name, hash) if hash[_primary] == fk }
end
end
end

private def preload_relation(collection, out_collection : Array(Model::Resource), relation, pk_repo)
return if collection.empty?
_primary = relation.primary_field
_foreign = relation.foreign_field

unless pk_repo.has_key?(_primary)
array = pk_repo[_primary] = Array(DBAny).new(collection.size)
collection.each { |e| array << e.attribute(_primary) }
end

new_collection = relation.query(pk_repo[_primary]).db_results

name = relation.name
if new_collection.empty?
collection.each(&.relation_retrieved(name))
else
primary_fields = pk_repo[_primary]
collection.each_with_index do |mod, i|
pv = primary_fields[i]
# TODO: check if deleting elements from array will increase performance
new_collection.each { |hash| out_collection << mod.append_relation(name, hash) if hash[_foreign] == pv }
end
pair[1].preload_relation(repo[pair[0]], repo[index + 1].as(Array(Model::Resource)), pk_repo[index])
end
end
end
Expand Down
25 changes: 25 additions & 0 deletions src/jennifer/relation/base.cr
Expand Up @@ -12,6 +12,8 @@ module Jennifer
abstract def join_condition(a, b)
abstract def query(a)
abstract def insert(a, b)
# Preloads relation into *collection* from *out_collection* depending on keys from *pk_repo*.
abstract def preload_relation(collection, out_collection, pk_repo)
end

# T - related model
Expand Down Expand Up @@ -98,6 +100,29 @@ module Jennifer
def primary_field
@primary ||= Q.primary_field_name
end

def preload_relation(collection, out_collection : Array(Model::Resource), pk_repo)
return if collection.empty?

unless pk_repo.has_key?(primary_field)
array = pk_repo[primary_field] = Array(DBAny).new(collection.size)
collection.each { |e| array << e.attribute(primary_field) }
end

new_collection = query(pk_repo[primary_field]).db_results

name = self.name
if new_collection.empty?
collection.each(&.relation_retrieved(name))
else
primary_fields = pk_repo[primary_field]
collection.each_with_index do |mod, i|
pv = primary_fields[i]
# TODO: check if deleting elements from array will increase performance
new_collection.each { |hash| out_collection << mod.append_relation(name, hash) if hash[foreign_field] == pv }
end
end
end
end
end
end
24 changes: 24 additions & 0 deletions src/jennifer/relation/belongs_to.cr
Expand Up @@ -108,6 +108,30 @@ module Jennifer
def primary_field
@primary ||= T.primary_field_name
end

def preload_relation(collection, out_collection : Array(Model::Resource), pk_repo)
return if collection.empty?
_primary = primary_field
_foreign = foreign_field

unless pk_repo.has_key?(_foreign)
array = pk_repo[_foreign] = Array(DBAny).new(collection.size)
collection.each { |e| array << e.attribute(_foreign) }
end

new_collection = query(pk_repo[_foreign]).db_results

name = self.name
if new_collection.empty?
collection.each(&.relation_retrieved(name))
else
foreign_fields = pk_repo[_foreign]
collection.each_with_index do |mod, i|
fk = foreign_fields[i]
new_collection.each { |hash| out_collection << mod.append_relation(name, hash) if hash[_primary] == fk }
end
end
end
end
end
end
27 changes: 27 additions & 0 deletions src/jennifer/relation/many_to_many.cr
Expand Up @@ -74,6 +74,33 @@ module Jennifer
@association_foreign || T.to_s.foreign_key
end

def preload_relation(collection, out_collection : Array(Model::Resource), pk_repo)
return if collection.empty?
_primary = primary_field

unless pk_repo.has_key?(_primary)
array = pk_repo[_primary] = Array(DBAny).new(collection.size)
collection.each { |e| array << e.attribute(_primary) }
end

join_fk = "__join_fk__"
query = query(pk_repo[_primary])
fields = query._select_fields
fields << QueryBuilder::Criteria.new(foreign_field, join_table!).alias(join_fk)
new_collection = query.select(fields).db_results

name = self.name
if new_collection.empty?
collection.each(&.relation_retrieved(name))
else
primary_fields = pk_repo[_primary]
collection.each_with_index do |mod, i|
pv = primary_fields[i]
new_collection.each { |hash| out_collection << mod.append_relation(name, hash) if hash[join_fk] == pv }
end
end
end

private def add_join_table_record(obj, rel)
adapter.insert(
join_table!,
Expand Down

0 comments on commit 0483bf9

Please sign in to comment.