1
0
Fork 0
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:
Nick Kallen 2007-12-30 23:59:29 -08:00
parent 1c1c878e2d
commit bd5a4d6d22
12 changed files with 142 additions and 30 deletions

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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