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

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