module Bmg::Sql::Support
Public Instance Methods
_order_all(tables, joins, result)
click to toggle source
# File lib/bmg/sql/support/from_clause_orderer.rb, line 110 def _order_all(tables, joins, result) if tables.empty? and joins.empty? # end or recusion result elsif tables.empty? # Why will this never happen exactly?? raise NotImplementedError, "Orphan joins: `#{joins.inspect}`" else # Greedy strategy: we take the first table in the list and keep the # rest for recursion later table, tables_tail = tables.first, tables[1..-1] # Split the remaining joins in two lists: those referencing only # introduced tables, and those making forward references on, joins_tail = split_joins(joins, table, tables_tail) # Decide which kind of join it is, according to the result and # the number of join clauses that will be used join_kind = if result.empty? :base elsif table.last == :left_join :left_join elsif on.empty? :cross_join else :inner_join end # Compute the AND([eq]) predicate on selected join clauses predicate = on.inject(nil){|p,clause| p.nil? ? clause : Predicate::Factory.and(p, clause) } # Recurse with that new clause in the result clause = [ join_kind, table[0], predicate ] _order_all(tables_tail, joins_tail, result + [clause]) end end
split_joins(joins, table, tables_tail)
click to toggle source
Given a list of join `ti.attri = tj.attrj` clauses, a newly introduced ti `table`, and a set of non-yet-introduced tables `tables_tail`,…
… split the joins in two sublists: those making references to table `ti` and making no reference to non introduced tables, and the others.
# File lib/bmg/sql/support/from_clause_orderer.rb, line 154 def split_joins(joins, table, tables_tail) joins.partition{|j| uses?(j, table[0]) && !tables_tail.find{|t| uses?(j, t[0]) } } end
uses?(condition, table)
click to toggle source
Returns whether the join conditions references the given table
# File lib/bmg/sql/support/from_clause_orderer.rb, line 163 def uses?(condition, table) name = table.as_name.to_s left_name = var_name(condition[1]) right_name = var_name(condition[2]) (left_name == name) or (right_name == name) end
var_name(qualified)
click to toggle source
Given a `ti.attri` expression (AST node), returns `ti`
# File lib/bmg/sql/support/from_clause_orderer.rb, line 171 def var_name(qualified) case qualified.first when :qualified_identifier then qualified[1].to_s when :qualified_name then qualified[1][1].to_s else raise NotImplementedError, "Unexpected qualified name `#{qualified.inspect}`" end end