module Card::Query::AbstractQuery::Tie
The “Tie” methods support tying two queries (CardQuery
, ReferenceQuery
, etc) together. The “fasten” variable determines which tying strategy is used.
We currently support three values for “fasten”: :join, :exist, and :in
In concept, here’s how the different strategies would tie table A to table B in SQL assuming A.id = B.a_id
-
:join … FROM A JOIN B ON A.id = B.a_id
-
:exist … FROM A WHERE EXISTS (SELECT * FROM B WHERE A.id = B.a_id …)
-
:in … FROM A WHERE A.id IN (SELECT B.a_id FROM B WHERE …)
The different strategies will return the same values but the relative speed is context dependent.
Public Instance Methods
fasten()
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 52 def fasten @fasten ||= root? ? :join : inherit_fasten end
fasten_tie(subquery, fields={})
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 31 def fasten_tie subquery, fields={} method = "tie_with_#{subquery.fasten}" send method, subquery, fields subquery end
id_from_val(val)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 94 def id_from_val val case val when Integer then val when String, Symbol then val.card_id || -999 end end
inherit_fasten()
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 73 def inherit_fasten superfasten = superquery.fasten superfasten == :direct ? superquery.inherit_fasten : superfasten end
left_join?(subquery)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 63 def left_join? subquery current_conjunction == "or" || subquery.negate # reverse conjunction if negated? end
list_of_ids?(val)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 109 def list_of_ids? val return unless val.is_a? Array !val.find { |v| !id_from_val v } end
negate_join(subquery, join, fields)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 68 def negate_join subquery, join, fields subquery.conditions_on_join = join add_condition "#{subquery.fld fields[:to]} is null" end
op_and_id_or_ids_from_val(val)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 101 def op_and_id_or_ids_from_val val if (single_id = id_from_val val) "= #{single_id}" elsif list_of_ids? val "in (#{val.map { |v| id_from_val v }.join ', '})" end end
restrict(id_field, val)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 86 def restrict id_field, val if (id = id_from_val val) interpret id_field => id else tie :card, val, from: id_field end end
super_conditions(fields)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 78 def super_conditions fields superfield fields[:to], fields[:from] end
superfield(myfield, superfield)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 82 def superfield myfield, superfield add_condition "#{fld myfield} = #{superquery.fld superfield}" end
tie(subquery_type, val, fields={})
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 19 def tie subquery_type, val, fields={}, subquery_args={} subquery = tie_subquery subquery_type, subquery_args subquery.interpret val fields = { from: :id, to: :id }.merge fields fasten_tie subquery, fields end
tie_subquery(subquery_type, subquery_args)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 26 def tie_subquery subquery_type, subquery_args subquery_args[:class] = Query.class_for subquery_type subquery(subquery_args) end
tie_with_exist(subquery, fields)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 48 def tie_with_exist subquery, fields subquery.super_conditions fields if fields.present? end
tie_with_in(subquery, fields)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 43 def tie_with_in subquery, fields subquery.mods[:return] = fields[:to] subquery.mods[:in_field] = fld(fields[:from]) end
tie_with_join(subquery, fields={})
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 37 def tie_with_join subquery, fields={} join = Join.new tie_with_join_args(subquery, fields) negate_join(subquery, join, fields) if subquery.negate joins << join end
tie_with_join_args(subquery, fields)
click to toggle source
# File lib/card/query/abstract_query/tie.rb, line 56 def tie_with_join_args subquery, fields args = { from: self, from_field: fields[:from], to: subquery, to_field: fields[:to] } args[:side] = :left if left_join? subquery args end