lib/spiderfw/model/mappers/db_mapper.rb in spiderfw-0.5.10 vs lib/spiderfw/model/mappers/db_mapper.rb in spiderfw-0.5.11
- old
+ new
@@ -84,12 +84,14 @@
values = {}
obj.no_autoload do
@model.each_element do |element|
next if !mapped?(element) || element.integrated?
next if save_mode == :update && !obj.element_modified?(element)
- if (save_mode == :insert && element.attributes[:autoincrement] && !schema.attributes(element.name)[:autoincrement])
- obj.set(element.name, @storage.sequence_next(schema.sequence(element.name)))
+ if (save_mode == :insert)
+ if element.attributes[:autoincrement] && !schema.attributes(element.name)[:autoincrement]
+ obj.set(element.name, @storage.sequence_next(schema.sequence(element.name)))
+ end
end
if (!element.multiple?)
next if (save_mode == :update && element.primary_key?)
next if (element.model? && !schema.has_foreign_fields?(element.name))
next if (element.model? && (!(element_val = obj.get(element)) || !obj.get(element).primary_keys_set?))
@@ -330,23 +332,23 @@
elements.each do |el|
element = @model.elements[el.to_sym]
next if !element || !element.type || element.integrated?
if !element.model?
field = schema.field(el)
+ primary_keys << field if model_pks.include?(el)
unless seen_fields[field.name]
keys << field
- primary_keys << field if model_pks.include?(el)
seen_fields[field.name] = true
end
elsif !element.attributes[:junction]
if schema.has_foreign_fields?(el)
element.model.primary_keys.each do |key|
field = schema.foreign_key_field(el, key.name)
raise "Can't find a foreign key field for key #{key.name} of element #{el} of model #{@model}" unless field
+ primary_keys << field if model_pks.include?(el)
unless seen_fields[field.name]
keys << field
- primary_keys << field if model_pks.include?(el)
seen_fields[field.name] = true
end
end
end
sub_request = query.request[element.name]
@@ -407,11 +409,11 @@
joins = prepare_joins(joins)
return nil if (keys.empty?)
return {
:query_type => :select,
:keys => keys,
- :primary_keys => primary_keys,
+ :primary_keys => primary_keys.uniq,
:tables => tables,
:condition => condition,
:joins => joins,
:order => order,
:offset => query.offset,
@@ -478,28 +480,44 @@
joins = options[:joins] || []
remaining_condition = Condition.new # TODO: implement
cond[:conj] = condition.conjunction.to_s
cond[:values] = []
- # find out which elements have non nil conditions to figure out joins
- def get_not_nil(model, condition, not_nil)
- condition.all_each_with_comparison do |k, v, comp|
+
+
+ def get_join_info(model, condition)
+ join_info = {}
+ condition.each_with_comparison do |k, v, comp|
next unless k.respond_to?(:to_sym)
element = model.elements[k.to_sym]
next unless element
next unless model.mapper.mapped?(element)
next unless element.model?
- not_nil[k] = {} if !v.nil? || comp != '='
- get_not_nil(element.model, v, not_nil[k]) if v.is_a?(Condition)
+ join_info[k.to_s] = true if !v.nil? || comp != '='
+ if v.is_a?(Spider::Model::Condition)
+ el_join_info = get_join_info(element.model, v)
+ el_join_info.each do |jk, jv|
+ join_info["#{k}.#{jk}"] = jv
+ end
+ end
end
+ condition.subconditions.each do |sub_cond|
+ sub_join_info = get_join_info(model, sub_cond)
+ if condition.conjunction == :or
+ join_info.each_key do |k|
+ join_info.delete(k) unless sub_join_info[k]
+ end
+ else
+ join_info.merge!(sub_join_info)
+ end
+ end
+ join_info
end
- not_nil = options[:not_nil]
- unless not_nil
- not_nil = {}
- get_not_nil(@model, condition, not_nil)
- end
+ join_info = options[:join_info]
+ join_info ||= get_join_info(@model, condition)
+
condition.each_with_comparison do |k, v, comp|
if k.is_a?(QueryFuncs::Function)
field = prepare_queryfunc(k)
cond[:values] << [field, comp, v]
@@ -507,10 +525,16 @@
next
end
element = model.elements[k.to_sym]
next unless model.mapper.mapped?(element)
if (element.model?)
+ el_join_info = {}
+ join_info.each do |jk, jv|
+ if jk.index(k.to_s+'.') == 0
+ el_join_info[jk[k.to_s.length..-1]] = jv
+ end
+ end
if (v && model.mapper.have_references?(element.name) && v.select{ |key, value|
!element.model.elements[key] || !element.model.elements[key].primary_key? }.empty?)
# 1/n <-> 1 with only primary keys
element_cond = {:conj => 'AND', :values => []}
v.each_with_comparison do |el_k, el_v, el_comp|
@@ -521,11 +545,11 @@
element_cond[:values] << field_cond
end
cond[:values] << element_cond
else
if (element.storage == model.mapper.storage)
- join_type = (v.nil? && comp == '=') ? :left : :inner
+ join_type = join_info[element.name.to_s] ? :inner : :left
sub_join = model.mapper.get_join(element, join_type)
# FIXME! cleanup, and apply the check to joins acquired in other places, too (maybe pass the current joins to get_join)
existent = joins.select{ |j| j[:to] == sub_join[:to] }
j_cnt = nil
had_join = false
@@ -540,29 +564,30 @@
end
end
sub_join[:as] = "#{sub_join[:to]}#{j_cnt}" if j_cnt
joins << sub_join unless had_join
- if v.nil? && comp == '=' && !not_nil[element.name]
+ if v.nil? && comp == '='
+ el_model_schema = model_schema
element_cond = {:conj => 'AND', :values => []}
if model.mapper.have_references?(element.name)
el_name = element.name
el_model = element.model
else
el_model = element.type
- model_schema = element.model.mapper.schema
+ el_model_schema = element.model.mapper.schema
el_name = element.attributes[:junction_their_element]
end
el_model.primary_keys.each do |k|
- field = model_schema.qualified_foreign_key_field(el_name, k.name)
+ field = el_model_schema.qualified_foreign_key_field(el_name, k.name)
field_cond = [field, comp, map_condition_value(element.model.elements[k.name].type, nil)]
element_cond[:values] << field_cond
end
cond[:values] << element_cond
elsif v
v = element.model.mapper.preprocess_condition(v)
- sub_condition, sub_joins = element.mapper.prepare_condition(v, :table => sub_join[:as], :joins => joins, :not_nil => not_nil[element.name])
+ sub_condition, sub_joins = element.mapper.prepare_condition(v, :table => sub_join[:as], :joins => joins, :join_info => el_join_info)
sub_condition[:table] = sub_join[:as] if sub_join[:as]
joins = sub_joins
cond[:values] << sub_condition
end
@@ -585,10 +610,10 @@
end
sub_sqls = []
sub_bind_values = []
condition.subconditions.each do |sub|
- sub_res = self.prepare_condition(sub, :joins => joins, :not_nil => not_nil)
+ sub_res = self.prepare_condition(sub, :joins => joins, :join_info => join_info)
cond[:values] << sub_res[0]
joins = sub_res[1]
remaining_condition += sub_res[2]
end
return [cond, joins, remaining_condition]