mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
before doing crazy
This commit is contained in:
parent
1c1c878e2d
commit
bd5a4d6d22
12 changed files with 142 additions and 30 deletions
|
@ -37,3 +37,6 @@ require 'sql_algebra/sql_builder/join_builder'
|
|||
require 'sql_algebra/sql_builder/inner_join_builder'
|
||||
require 'sql_algebra/sql_builder/left_outer_join_builder'
|
||||
require 'sql_algebra/sql_builder/equals_condition_builder'
|
||||
require 'sql_algebra/sql_builder/column_builder'
|
||||
require 'sql_algebra/sql_builder/conditions_builder'
|
||||
|
||||
|
|
|
@ -9,4 +9,10 @@ class BinaryPredicate < Predicate
|
|||
super and
|
||||
(attribute1.eql?(other.attribute1) and attribute2.eql?(other.attribute2))
|
||||
end
|
||||
|
||||
def to_sql(builder = ConditionsBuilder.new)
|
||||
builder.call do
|
||||
send(predicate_name, attribute1.to_sql(self), attribute2.to_sql(self))
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,4 +4,9 @@ class EqualityPredicate < BinaryPredicate
|
|||
((attribute1.eql?(other.attribute1) and attribute2.eql?(other.attribute2)) or
|
||||
(attribute1.eql?(other.attribute2) and attribute2.eql?(other.attribute1)))
|
||||
end
|
||||
|
||||
protected
|
||||
def predicate_name
|
||||
:equals
|
||||
end
|
||||
end
|
|
@ -32,4 +32,8 @@ class Attribute
|
|||
def =~(regexp)
|
||||
MatchPredicate.new(self, regexp)
|
||||
end
|
||||
|
||||
def to_sql(ignore_builder_because_i_can_only_exist_atomically)
|
||||
ColumnBuilder.new(relation.table, attribute_name)
|
||||
end
|
||||
end
|
|
@ -10,4 +10,40 @@ class JoinRelation < Relation
|
|||
((relation1 == other.relation1 and relation2 == other.relation2) or
|
||||
(relation2 == other.relation1 and relation1 == other.relation2))
|
||||
end
|
||||
|
||||
def to_sql(builder = SelectBuilder.new)
|
||||
enclosed_join_name, enclosed_predicates = join_name, predicates
|
||||
relation2.to_sql(Adapter.new(relation1.to_sql(builder)) do
|
||||
define_method :from do |table|
|
||||
send(enclosed_join_name, table) do
|
||||
enclosed_predicates.each do |predicate|
|
||||
predicate.to_sql(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
class Adapter
|
||||
instance_methods.each { |m| undef_method m unless m =~ /^__|^instance_eval/ }
|
||||
|
||||
def initialize(adaptee, &block)
|
||||
@adaptee = adaptee
|
||||
(class << self; self end).class_eval do
|
||||
(adaptee.methods - instance_methods).each { |m| delegate m, :to => :@adaptee }
|
||||
end
|
||||
(class << self; self end).class_eval(&block)
|
||||
end
|
||||
|
||||
def call(&block)
|
||||
@caller = eval("self", block.binding)
|
||||
returning self do |adapter|
|
||||
instance_eval(&block)
|
||||
end
|
||||
end
|
||||
|
||||
def method_missing(method, *args, &block)
|
||||
@caller.send(method, *args, &block)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,4 +9,12 @@ class SelectionRelation < Relation
|
|||
def ==(other)
|
||||
relation == other.relation and predicate == other.predicate
|
||||
end
|
||||
|
||||
def to_sql(builder = SelectBuilder.new)
|
||||
relation.to_sql(builder).call do
|
||||
where do
|
||||
predicate.to_sql(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,8 +5,8 @@ class TableRelation < Relation
|
|||
@table = table
|
||||
end
|
||||
|
||||
def to_sql
|
||||
SelectBuilder.new do
|
||||
def to_sql(builder = SelectBuilder.new)
|
||||
builder.call do
|
||||
select :*
|
||||
from table
|
||||
end
|
||||
|
|
|
@ -4,22 +4,22 @@ describe BinaryPredicate do
|
|||
before do
|
||||
@relation1 = TableRelation.new(:foo)
|
||||
@relation2 = TableRelation.new(:bar)
|
||||
@attribute1 = Attribute.new(@relation1, :attribute_name)
|
||||
@attribute2 = Attribute.new(@relation2, :attribute_name)
|
||||
@attribute1 = Attribute.new(@relation1, :attribute_name1)
|
||||
@attribute2 = Attribute.new(@relation2, :attribute_name2)
|
||||
class ConcreteBinaryPredicate < BinaryPredicate
|
||||
def predicate_name
|
||||
:equals
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe BinaryPredicate, '#initialize' do
|
||||
describe '#initialize' do
|
||||
it "requires that both columns come from the same relation" do
|
||||
pending
|
||||
end
|
||||
end
|
||||
|
||||
describe BinaryPredicate, '==' do
|
||||
before do
|
||||
class ConcreteBinaryPredicate < BinaryPredicate
|
||||
end
|
||||
end
|
||||
|
||||
describe '==' do
|
||||
it "obtains if attribute1 and attribute2 are identical" do
|
||||
BinaryPredicate.new(@attribute1, @attribute2).should == BinaryPredicate.new(@attribute1, @attribute2)
|
||||
BinaryPredicate.new(@attribute1, @attribute2).should_not == BinaryPredicate.new(@attribute1, @attribute1)
|
||||
|
@ -30,4 +30,12 @@ describe BinaryPredicate do
|
|||
BinaryPredicate.new(@attribute1, @attribute2).should_not == ConcreteBinaryPredicate.new(@attribute1, @attribute2)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_sql' do
|
||||
it '' do
|
||||
ConcreteBinaryPredicate.new(@attribute1, @attribute2).to_sql.should == ConditionsBuilder.new do
|
||||
equals 'foo.attribute_name1', 'bar.attribute_name2'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,7 +6,7 @@ describe Attribute do
|
|||
@relation2 = TableRelation.new(:bar)
|
||||
end
|
||||
|
||||
describe Attribute, '#eql?' do
|
||||
describe '#eql?' do
|
||||
it "obtains if the relation and attribute name are identical" do
|
||||
Attribute.new(@relation1, :attribute_name).should be_eql(Attribute.new(@relation1, :attribute_name))
|
||||
Attribute.new(@relation1, :attribute_name).should_not be_eql(Attribute.new(@relation1, :another_attribute_name))
|
||||
|
@ -14,47 +14,52 @@ describe Attribute do
|
|||
end
|
||||
end
|
||||
|
||||
describe Attribute, 'predications' do
|
||||
describe 'predications' do
|
||||
before do
|
||||
@attribute1 = Attribute.new(@relation1, :attribute_name)
|
||||
@attribute2 = Attribute.new(@relation2, :attribute_name)
|
||||
end
|
||||
|
||||
describe Attribute, '==' do
|
||||
describe '==' do
|
||||
it "manufactures an equality predicate" do
|
||||
(@attribute1 == @attribute2).should == EqualityPredicate.new(@attribute1, @attribute2)
|
||||
end
|
||||
end
|
||||
|
||||
describe Attribute, '<' do
|
||||
describe '<' do
|
||||
it "manufactures a less-than predicate" do
|
||||
(@attribute1 < @attribute2).should == LessThanPredicate.new(@attribute1, @attribute2)
|
||||
end
|
||||
end
|
||||
|
||||
describe Attribute, '<=' do
|
||||
describe '<=' do
|
||||
it "manufactures a less-than or equal-to predicate" do
|
||||
(@attribute1 <= @attribute2).should == LessThanOrEqualToPredicate.new(@attribute1, @attribute2)
|
||||
end
|
||||
end
|
||||
|
||||
describe Attribute, '>' do
|
||||
describe '>' do
|
||||
it "manufactures a greater-than predicate" do
|
||||
(@attribute1 > @attribute2).should == GreaterThanPredicate.new(@attribute1, @attribute2)
|
||||
end
|
||||
end
|
||||
|
||||
describe Attribute, '>=' do
|
||||
describe '>=' do
|
||||
it "manufactures a greater-than or equal to predicate" do
|
||||
(@attribute1 >= @attribute2).should == GreaterThanOrEqualToPredicate.new(@attribute1, @attribute2)
|
||||
end
|
||||
end
|
||||
|
||||
describe Attribute, '=~' do
|
||||
describe '=~' do
|
||||
it "manufactures a match predicate" do
|
||||
(@attribute1 =~ /.*/).should == MatchPredicate.new(@attribute1, @attribute2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_sql' do
|
||||
it "manufactures a column" do
|
||||
Attribute.new(@relation1, :attribute_name).to_sql.should == ColumnBuilder.new(@relation1.table, :attribute_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
||||
|
||||
describe JoinOperation, 'between two relations' do
|
||||
describe 'between two relations' do
|
||||
before do
|
||||
@relation1 = TableRelation.new(:foo)
|
||||
@relation2 = TableRelation.new(:bar)
|
||||
end
|
||||
|
||||
describe JoinOperation, '==' do
|
||||
describe '==' do
|
||||
it "obtains if the relations of both joins are identical" do
|
||||
JoinOperation.new(@relation1, @relation2).should == JoinOperation.new(@relation1, @relation2)
|
||||
JoinOperation.new(@relation1, @relation2).should_not == JoinOperation.new(@relation1, @relation1)
|
||||
|
@ -17,7 +17,7 @@ describe JoinOperation, 'between two relations' do
|
|||
end
|
||||
end
|
||||
|
||||
describe JoinOperation, 'on' do
|
||||
describe 'on' do
|
||||
before do
|
||||
@predicate = Predicate.new
|
||||
@join_operation = JoinOperation.new(@relation1, @relation2)
|
||||
|
|
|
@ -1,20 +1,45 @@
|
|||
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
||||
|
||||
describe JoinRelation, 'between two relations' do
|
||||
describe 'between two relations' do
|
||||
before do
|
||||
@relation1 = TableRelation.new(:foo)
|
||||
@relation2 = TableRelation.new(:bar)
|
||||
@predicate = Predicate.new
|
||||
@predicate = EqualityPredicate.new(@relation1[:a], @relation2[:b])
|
||||
end
|
||||
|
||||
describe JoinRelation, '==' do
|
||||
it "obtains if the two relations and the predicate are identical" do
|
||||
describe '==' do
|
||||
it 'obtains if the two relations and the predicate are identical' do
|
||||
JoinRelation.new(@relation1, @relation2, @predicate).should == JoinRelation.new(@relation1, @relation2, @predicate)
|
||||
JoinRelation.new(@relation1, @relation2, @predicate).should_not == JoinRelation.new(@relation1, @relation1, @predicate)
|
||||
end
|
||||
|
||||
it "is commutative on the relations" do
|
||||
it 'is commutative on the relations' do
|
||||
JoinRelation.new(@relation1, @relation2, @predicate).should == JoinRelation.new(@relation2, @relation1, @predicate)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_sql' do
|
||||
before do
|
||||
@relation1 = @relation1.select(@relation1[:c] == @relation2[:d])
|
||||
class ConcreteJoinRelation < JoinRelation
|
||||
def join_name
|
||||
:inner_join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'manufactures sql joining the two tables on the predicate, merging the selects' do
|
||||
ConcreteJoinRelation.new(@relation1, @relation2, @predicate).to_sql.to_s.should == SelectBuilder.new do
|
||||
select :*
|
||||
from :foo do
|
||||
inner_join :bar do
|
||||
equals 'foo.a', 'bar.b'
|
||||
end
|
||||
end
|
||||
where do
|
||||
equals 'foo.c', 'bar.d'
|
||||
end
|
||||
end.to_s
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,7 +8,7 @@ describe SelectionRelation do
|
|||
@predicate2 = LessThanPredicate.new(@relation1[:age], 2)
|
||||
end
|
||||
|
||||
describe SelectionRelation, '==' do
|
||||
describe '==' do
|
||||
it "obtains if both the predicate and the relation are identical" do
|
||||
SelectionRelation.new(@relation1, @predicate1). \
|
||||
should == SelectionRelation.new(@relation1, @predicate1)
|
||||
|
@ -19,10 +19,22 @@ describe SelectionRelation do
|
|||
end
|
||||
end
|
||||
|
||||
describe SelectionRelation, '#initialize' do
|
||||
describe '#initialize' do
|
||||
it "manufactures nested selection relations if multiple predicates are provided" do
|
||||
SelectionRelation.new(@relation1, @predicate1, @predicate2). \
|
||||
should == SelectionRelation.new(SelectionRelation.new(@relation1, @predicate2), @predicate1)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_sql' do
|
||||
it "manufactures sql with where clause conditions" do
|
||||
SelectionRelation.new(@relation1, @predicate1).to_sql.should == SelectBuilder.new do
|
||||
select :*
|
||||
from :foo
|
||||
where do
|
||||
equals 'foo.id', 'bar.foo_id'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue