lib/spiderfw/model/mappers/db_mapper.rb in spiderfw-0.6.18 vs lib/spiderfw/model/mappers/db_mapper.rb in spiderfw-0.6.19

- old
+ new

@@ -492,44 +492,63 @@ remaining_condition = Condition.new # TODO: implement cond[:conj] = condition.conjunction.to_s cond[:values] = [] - + # Returns an hash of elements that need an "inner" join 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? - join_info[k.to_s] = true if !v.nil? || (comp != '=' && comp != 'like' && comp != 'ilike') + join_info[k.to_s] = if v.nil? + comp == '<>' ? true : false + else + comp == '<>' ? false : true + end if v.is_a?(Spider::Model::Condition) el_join_info = get_join_info(element.model, v) + has_true = false + has_false = false el_join_info.each do |jk, jv| join_info["#{k}.#{jk}"] = jv + has_true = true if jv + has_false = true unless jv end + if (v.conjunction == :and && has_true) || (has_true && !has_false) + join_info[k.to_s] = true + elsif (v.conjunction == :or && has_false) || (has_false && !has_true) + join_info[k.to_s] = false + end end end + sub = {} condition.subconditions.each do |sub_cond| + next if sub_cond.empty? 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] + sub_join_info.each_key do |k| + if condition.conjunction == :or + sub[k] = true if sub_join_info[k] && sub[k] != false + sub[k] = false unless sub_join_info + else + sub[k] = true if sub_join_info[k] end - else - join_info.merge!(sub_join_info) end end + join_info.merge!(sub) join_info 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] joins += field.joins @@ -539,11 +558,11 @@ 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 + el_join_info[jk[k.to_s.length+1..-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 @@ -555,19 +574,20 @@ field_cond = [field, op, map_condition_value(element.model.elements[el_k.to_sym].type, el_v)] element_cond[:values] << field_cond end cond[:values] << element_cond else - if (element.storage == model.mapper.storage) + if element.storage == model.mapper.storage 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 existent.each do |j| if sub_join[:to] == j[:to] && sub_join[:keys] == j[:keys] && sub_join[:conditions] == j[:conditions] + # if any condition allows a left join, then a left join should be used here as well j[:type] = :left if sub_join[:type] == :left sub_join = j had_join = true break else @@ -593,10 +613,9 @@ 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, :join_info => el_join_info) sub_condition[:table] = sub_join[:as] if sub_join[:as] joins = sub_joins cond[:values] << sub_condition end