Class: Bmg::Sql::Support::FromClauseOrderer
- Inherits:
-
Object
- Object
- Bmg::Sql::Support::FromClauseOrderer
- Defined in:
- lib/bmg/sql/support/from_clause_orderer.rb
Instance Method Summary collapse
-
#call(sexpr) ⇒ Object
Given a ‘from_clause` AST as input, e.g.
Instance Method Details
#call(sexpr) ⇒ Object
Given a ‘from_clause` AST as input, e.g.
[ :from_clause,
[ :cross_join
[ :inner_join,
[ :inner_join,
[ :table_as, "suppliers", "s" ],
[ :table_as, "supplies", "sp" ],
[ :eq, [ :qualified, "s", "sid" ], [ :qualified, "sp", "sid" ] ]
],
[ :table_as, "parts", "p" ],
[ :eq, [ :qualified, "p", "pid" ], [ :qualified "sp", "pid" ] ]
],
[ :table_as, "cities", "c" ],
]
]
Generates a relationally equivalent list of (type,table,predicate) triplets, where:
-
type is :base, :cross_join, :inner_join, or :left_join
-
table is table_as, native_table_as or subquery_as
-
predicate is a join predicate ‘ti.attri = tj.attrj AND …`
So that
1) the types are observed in strict increasing order (one :base, zero
or more :cross_join, zero or more :inner_join, zero or more :left_join)
2) the list is such that it can be safely written as an expression
of the following SQL syntax:
t1 # [ :base, t1, nil ]
cross_join t2 # [ :cross_join, t2, nil ]
cross_join t3 # [ :cross_join, t3, nil ]
inner_join t4 ON p4 # [ :inner_join, t4, p4 ]
inner_join t5 ON p5 # [ :inner_join, t5, p5 ]
left_join t6 ON p6 # [ :left_join, t6, p6 ]
that is, the linearization is correct only if each predicate `pi`
only makes reference to tables introduced before it (no forward
reference).
For the example above, a solution might be:
[
[ :base, [ :table_as, "suppliers", "s" ], nil ],
[ :cross_join, [ :table_as, "cities", "c" ], nil ],
[ :inner_join, [ :table_as, "supplies", "sp" ],
[ :eq, [ :qualified, "s", "sid" ], [ :qualified, "sp", "sid" ] ] ],
[ :inner_join, [ :table_as, "parts", "p" ],
[ :eq, [ :qualified, "p", "pid" ], [ :qualified "sp", "pid" ] ] ]
]
A NotImplementedError may be raised if no linearization can be found.
62 63 64 65 66 67 68 69 70 |
# File 'lib/bmg/sql/support/from_clause_orderer.rb', line 62 def call(sexpr) # The algorithm works in two phases: we first collect all table # references and JOIN clauses by simple inspection of the AST. tables, joins = collect(sexpr) # Then we order the tables and join clauses so as to find the # linearization. order_all(tables, joins) end |