aboutsummaryrefslogtreecommitdiffstats
path: root/spec
diff options
context:
space:
mode:
authorEmilio Tagua <miloops@gmail.com>2009-05-26 12:41:52 -0300
committerEmilio Tagua <miloops@gmail.com>2009-05-26 12:41:52 -0300
commitc9bbea6115be520dbd47bd30108c5622289deb26 (patch)
treeec418e01954c1bd2dcfebc7fbc8220fb04b50baf /spec
parentae1e0ac5e98a7e5a2894d0a431f8c34af6575cae (diff)
parent86364591af807ed3fa4a7304f53e6f3458cb4961 (diff)
downloadrails-c9bbea6115be520dbd47bd30108c5622289deb26.tar.gz
rails-c9bbea6115be520dbd47bd30108c5622289deb26.tar.bz2
rails-c9bbea6115be520dbd47bd30108c5622289deb26.zip
Merge commit 'brynary/master'
Conflicts: lib/arel.rb lib/arel/session.rb
Diffstat (limited to 'spec')
-rw-r--r--spec/arel/algebra/unit/predicates/binary_spec.rb33
-rw-r--r--spec/arel/algebra/unit/predicates/equality_spec.rb (renamed from spec/arel/unit/predicates/equality_spec.rb)34
-rw-r--r--spec/arel/algebra/unit/predicates/in_spec.rb10
-rw-r--r--spec/arel/algebra/unit/primitives/attribute_spec.rb (renamed from spec/arel/unit/primitives/attribute_spec.rb)104
-rw-r--r--spec/arel/algebra/unit/primitives/expression_spec.rb (renamed from spec/arel/unit/primitives/expression_spec.rb)22
-rw-r--r--spec/arel/algebra/unit/primitives/value_spec.rb15
-rw-r--r--spec/arel/algebra/unit/relations/alias_spec.rb16
-rw-r--r--spec/arel/algebra/unit/relations/delete_spec.rb9
-rw-r--r--spec/arel/algebra/unit/relations/group_spec.rb10
-rw-r--r--spec/arel/algebra/unit/relations/insert_spec.rb9
-rw-r--r--spec/arel/algebra/unit/relations/join_spec.rb26
-rw-r--r--spec/arel/algebra/unit/relations/order_spec.rb21
-rw-r--r--spec/arel/algebra/unit/relations/project_spec.rb34
-rw-r--r--spec/arel/algebra/unit/relations/relation_spec.rb (renamed from spec/arel/unit/relations/relation_spec.rb)42
-rw-r--r--spec/arel/algebra/unit/relations/skip_spec.rb10
-rw-r--r--spec/arel/algebra/unit/relations/table_spec.rb39
-rw-r--r--spec/arel/algebra/unit/relations/take_spec.rb10
-rw-r--r--spec/arel/algebra/unit/relations/update_spec.rb9
-rw-r--r--spec/arel/algebra/unit/relations/where_spec.rb18
-rw-r--r--spec/arel/algebra/unit/session/session_spec.rb (renamed from spec/arel/unit/session/session_spec.rb)12
-rw-r--r--spec/arel/engines/memory/integration/joins/cross_engine_spec.rb48
-rw-r--r--spec/arel/engines/memory/unit/relations/array_spec.rb32
-rw-r--r--spec/arel/engines/memory/unit/relations/insert_spec.rb28
-rw-r--r--spec/arel/engines/memory/unit/relations/join_spec.rb31
-rw-r--r--spec/arel/engines/memory/unit/relations/order_spec.rb27
-rw-r--r--spec/arel/engines/memory/unit/relations/project_spec.rb27
-rw-r--r--spec/arel/engines/memory/unit/relations/skip_spec.rb26
-rw-r--r--spec/arel/engines/memory/unit/relations/take_spec.rb26
-rw-r--r--spec/arel/engines/memory/unit/relations/where_spec.rb39
-rw-r--r--spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb209
-rw-r--r--spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb167
-rw-r--r--spec/arel/engines/sql/integration/joins/with_compounds_spec.rb107
-rw-r--r--spec/arel/engines/sql/unit/engine_spec.rb45
-rw-r--r--spec/arel/engines/sql/unit/predicates/binary_spec.rb117
-rw-r--r--spec/arel/engines/sql/unit/predicates/equality_spec.rb46
-rw-r--r--spec/arel/engines/sql/unit/predicates/in_spec.rb86
-rw-r--r--spec/arel/engines/sql/unit/predicates/predicates_spec.rb65
-rw-r--r--spec/arel/engines/sql/unit/primitives/attribute_spec.rb32
-rw-r--r--spec/arel/engines/sql/unit/primitives/expression_spec.rb24
-rw-r--r--spec/arel/engines/sql/unit/primitives/literal_spec.rb23
-rw-r--r--spec/arel/engines/sql/unit/primitives/value_spec.rb (renamed from spec/arel/unit/primitives/value_spec.rb)17
-rw-r--r--spec/arel/engines/sql/unit/relations/alias_spec.rb43
-rw-r--r--spec/arel/engines/sql/unit/relations/delete_spec.rb63
-rw-r--r--spec/arel/engines/sql/unit/relations/group_spec.rb56
-rw-r--r--spec/arel/engines/sql/unit/relations/insert_spec.rb107
-rw-r--r--spec/arel/engines/sql/unit/relations/join_spec.rb57
-rw-r--r--spec/arel/engines/sql/unit/relations/order_spec.rb113
-rw-r--r--spec/arel/engines/sql/unit/relations/project_spec.rb110
-rw-r--r--spec/arel/engines/sql/unit/relations/skip_spec.rb32
-rw-r--r--spec/arel/engines/sql/unit/relations/table_spec.rb69
-rw-r--r--spec/arel/engines/sql/unit/relations/take_spec.rb32
-rw-r--r--spec/arel/engines/sql/unit/relations/update_spec.rb151
-rw-r--r--spec/arel/engines/sql/unit/relations/where_spec.rb56
-rw-r--r--spec/arel/integration/joins/with_adjacency_spec.rb139
-rw-r--r--spec/arel/integration/joins/with_aggregations_spec.rb89
-rw-r--r--spec/arel/integration/joins/with_compounds_spec.rb65
-rw-r--r--spec/arel/unit/predicates/binary_spec.rb95
-rw-r--r--spec/arel/unit/predicates/in_spec.rb58
-rw-r--r--spec/arel/unit/predicates/predicates_spec.rb33
-rw-r--r--spec/arel/unit/relations/alias_spec.rb36
-rw-r--r--spec/arel/unit/relations/delete_spec.rb42
-rw-r--r--spec/arel/unit/relations/group_spec.rb32
-rw-r--r--spec/arel/unit/relations/insert_spec.rb71
-rw-r--r--spec/arel/unit/relations/join_spec.rb54
-rw-r--r--spec/arel/unit/relations/order_spec.rb66
-rw-r--r--spec/arel/unit/relations/project_spec.rb81
-rw-r--r--spec/arel/unit/relations/skip_spec.rb20
-rw-r--r--spec/arel/unit/relations/table_spec.rb88
-rw-r--r--spec/arel/unit/relations/take_spec.rb20
-rw-r--r--spec/arel/unit/relations/update_spec.rb81
-rw-r--r--spec/arel/unit/relations/where_spec.rb40
-rw-r--r--spec/connections/mysql_connection.rb15
-rw-r--r--spec/connections/postgresql_connection.rb14
-rw-r--r--spec/connections/sqlite3_connection.rb25
-rw-r--r--spec/doubles/database.rb51
-rw-r--r--spec/doubles/hash.rb8
-rw-r--r--spec/matchers/be_like.rb10
-rw-r--r--spec/matchers/disambiguate_attributes.rb10
-rw-r--r--spec/matchers/hash_the_same_as.rb10
-rw-r--r--spec/schemas/mysql_schema.rb18
-rw-r--r--spec/schemas/postgresql_schema.rb18
-rw-r--r--spec/schemas/sqlite3_schema.rb18
-rw-r--r--spec/spec_helper.rb31
83 files changed, 2640 insertions, 1292 deletions
diff --git a/spec/arel/algebra/unit/predicates/binary_spec.rb b/spec/arel/algebra/unit/predicates/binary_spec.rb
new file mode 100644
index 0000000000..14fd7ab21b
--- /dev/null
+++ b/spec/arel/algebra/unit/predicates/binary_spec.rb
@@ -0,0 +1,33 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Binary do
+ before do
+ @relation = Table.new(:users)
+ @attribute1 = @relation[:id]
+ @attribute2 = @relation[:name]
+ class ConcreteBinary < Binary
+ end
+ end
+
+ describe '#bind' do
+ before do
+ @another_relation = @relation.alias
+ end
+
+ describe 'when both operands are attributes' do
+ it "manufactures an expression with the attributes bound to the relation" do
+ ConcreteBinary.new(@attribute1, @attribute2).bind(@another_relation). \
+ should == ConcreteBinary.new(@another_relation[@attribute1], @another_relation[@attribute2])
+ end
+ end
+
+ describe 'when an operand is a value' do
+ it "manufactures an expression with unmodified values" do
+ ConcreteBinary.new(@attribute1, "asdf").bind(@another_relation). \
+ should == ConcreteBinary.new(@attribute1.find_correlate_in(@another_relation), "asdf".find_correlate_in(@another_relation))
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/unit/predicates/equality_spec.rb b/spec/arel/algebra/unit/predicates/equality_spec.rb
index 8a58ba3096..af91f8b51b 100644
--- a/spec/arel/unit/predicates/equality_spec.rb
+++ b/spec/arel/algebra/unit/predicates/equality_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
module Arel
describe Equality do
@@ -8,42 +8,20 @@ module Arel
@attribute1 = @relation1[:id]
@attribute2 = @relation2[:user_id]
end
-
- describe '==' do
+
+ describe '==' do
it "obtains if attribute1 and attribute2 are identical" do
Equality.new(@attribute1, @attribute2).should == Equality.new(@attribute1, @attribute2)
Equality.new(@attribute1, @attribute2).should_not == Equality.new(@attribute1, @attribute1)
end
-
+
it "obtains if the concrete type of the predicates are identical" do
Equality.new(@attribute1, @attribute2).should_not == Binary.new(@attribute1, @attribute2)
end
-
+
it "is commutative on the attributes" do
Equality.new(@attribute1, @attribute2).should == Equality.new(@attribute2, @attribute1)
end
end
-
- describe '#to_sql' do
- describe 'when relating to a non-nil value' do
- it "manufactures an equality predicate" do
- Equality.new(@attribute1, @attribute2).to_sql.should be_like("
- `users`.`id` = `photos`.`user_id`
- ")
- end
- end
-
- describe 'when relation to a nil value' do
- before do
- @nil = nil
- end
-
- it "manufactures an is null predicate" do
- Equality.new(@attribute1, @nil).to_sql.should be_like("
- `users`.`id` IS NULL
- ")
- end
- end
- end
end
-end \ No newline at end of file
+end
diff --git a/spec/arel/algebra/unit/predicates/in_spec.rb b/spec/arel/algebra/unit/predicates/in_spec.rb
new file mode 100644
index 0000000000..a8a15ce4e3
--- /dev/null
+++ b/spec/arel/algebra/unit/predicates/in_spec.rb
@@ -0,0 +1,10 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe In do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+ end
+end
diff --git a/spec/arel/unit/primitives/attribute_spec.rb b/spec/arel/algebra/unit/primitives/attribute_spec.rb
index b341c6f88e..2ca63ba48e 100644
--- a/spec/arel/unit/primitives/attribute_spec.rb
+++ b/spec/arel/algebra/unit/primitives/attribute_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
module Arel
describe Attribute do
@@ -6,57 +6,71 @@ module Arel
@relation = Table.new(:users)
@attribute = @relation[:id]
end
-
+
+ describe "#inspect" do
+ it "returns a simple, short inspect string" do
+ @attribute.inspect.should == "<Attribute id>"
+ end
+ end
+
describe Attribute::Transformations do
describe '#as' do
it "manufactures an aliased attributed" do
@attribute.as(:alias).should == Attribute.new(@relation, @attribute.name, :alias => :alias, :ancestor => @attribute)
end
end
-
+
describe '#bind' do
it "manufactures an attribute with the relation bound and self as an ancestor" do
derived_relation = @relation.where(@relation[:id].eq(1))
@attribute.bind(derived_relation).should == Attribute.new(derived_relation, @attribute.name, :ancestor => @attribute)
end
-
+
it "returns self if the substituting to the same relation" do
@attribute.bind(@relation).should == @attribute
end
end
-
+
describe '#to_attribute' do
- it "returns self" do
- @attribute.to_attribute.should == @attribute
+ describe 'when the given relation is the same as the attributes relation' do
+ it "returns self" do
+ @attribute.to_attribute(@relation).should == @attribute
+ end
+ end
+
+ describe 'when the given relation differs from the attributes relation' do
+ it 'binds to the new relation' do
+ @attribute.to_attribute(new_relation = @relation.alias).should == @attribute.bind(new_relation)
+ end
end
end
end
-
+
describe '#column' do
it "returns the corresponding column in the relation" do
@attribute.column.should == @relation.column_for(@attribute)
end
end
-
+
describe '#engine' do
it "delegates to its relation" do
Attribute.new(@relation, :id).engine.should == @relation.engine
end
end
-
+
describe Attribute::Congruence do
describe '/' do
before do
@aliased_relation = @relation.alias
@doubly_aliased_relation = @aliased_relation.alias
end
-
+
describe 'when dividing two unrelated attributes' do
it "returns 0.0" do
(@relation[:id] / @relation[:name]).should == 0.0
end
end
-
+
describe 'when dividing two matching attributes' do
it 'returns a the highest score for the most similar attributes' do
(@aliased_relation[:id] / @relation[:id]) \
@@ -67,97 +81,103 @@ module Arel
end
end
end
-
- describe '#to_sql' do
- describe 'for a simple attribute' do
- it "manufactures sql with an alias" do
- @attribute.to_sql.should be_like("`users`.`id`")
- end
- end
- end
-
+
describe Attribute::Predications do
before do
@attribute = Attribute.new(@relation, :name)
end
-
+
describe '#eq' do
it "manufactures an equality predicate" do
@attribute.eq('name').should == Equality.new(@attribute, 'name')
end
end
-
+
describe '#lt' do
it "manufactures a less-than predicate" do
@attribute.lt(10).should == LessThan.new(@attribute, 10)
end
end
-
+
describe '#lteq' do
it "manufactures a less-than or equal-to predicate" do
@attribute.lteq(10).should == LessThanOrEqualTo.new(@attribute, 10)
end
end
-
+
describe '#gt' do
it "manufactures a greater-than predicate" do
@attribute.gt(10).should == GreaterThan.new(@attribute, 10)
end
end
-
+
describe '#gteq' do
it "manufactures a greater-than or equal-to predicate" do
@attribute.gteq(10).should == GreaterThanOrEqualTo.new(@attribute, 10)
end
end
-
+
describe '#matches' do
it "manufactures a match predicate" do
@attribute.matches(/.*/).should == Match.new(@attribute, /.*/)
end
end
-
+
describe '#in' do
it "manufactures an in predicate" do
@attribute.in(1..30).should == In.new(@attribute, (1..30))
end
end
end
-
+
describe Attribute::Expressions do
before do
- @attribute = Attribute.new(@relation, :name)
+ @attribute = Attribute.new(@relation, :name)
end
-
+
describe '#count' do
it "manufactures a count Expression" do
- @attribute.count.should == Expression.new(@attribute, "COUNT")
+ @attribute.count.should == Count.new(@attribute)
end
end
-
+
describe '#sum' do
it "manufactures a sum Expression" do
- @attribute.sum.should == Expression.new(@attribute, "SUM")
+ @attribute.sum.should == Sum.new(@attribute)
end
end
-
+
describe '#maximum' do
it "manufactures a maximum Expression" do
- @attribute.maximum.should == Expression.new(@attribute, "MAX")
+ @attribute.maximum.should == Maximum.new(@attribute)
end
end
-
+
describe '#minimum' do
it "manufactures a minimum Expression" do
- @attribute.minimum.should == Expression.new(@attribute, "MIN")
+ @attribute.minimum.should == Minimum.new(@attribute)
end
end
-
+
describe '#average' do
it "manufactures an average Expression" do
- @attribute.average.should == Expression.new(@attribute, "AVG")
+ @attribute.average.should == Average.new(@attribute)
+ end
+ end
+ end
+
+ describe Attribute::Orderings do
+ describe '#asc' do
+ it 'manufactures an ascending ordering' do
+ @attribute.asc.should == Ascending.new(@attribute)
end
- end
+ end
+
+ describe '#desc' do
+ it 'manufactures a descending ordering' do
+ @attribute.desc.should == Descending.new(@attribute)
+ end
+ end
end
end
-end \ No newline at end of file
+end
diff --git a/spec/arel/unit/primitives/expression_spec.rb b/spec/arel/algebra/unit/primitives/expression_spec.rb
index 4943f4ef33..768bb492a7 100644
--- a/spec/arel/unit/primitives/expression_spec.rb
+++ b/spec/arel/algebra/unit/primitives/expression_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
module Arel
describe Expression do
@@ -7,15 +7,21 @@ module Arel
@attribute = @relation[:id]
end
+ describe "#inspect" do
+ it "returns a simple, short inspect string" do
+ @attribute.count.inspect.should == "<Arel::Count <Attribute id>>"
+ end
+ end
+
describe Expression::Transformations do
before do
- @expression = Expression.new(@attribute, "COUNT")
+ @expression = Count.new(@attribute)
end
describe '#bind' do
it "manufactures an attribute with a rebound relation and self as the ancestor" do
derived_relation = @relation.where(@relation[:id].eq(1))
- @expression.bind(derived_relation).should == Expression.new(@attribute.bind(derived_relation), "COUNT", nil, @expression)
+ @expression.bind(derived_relation).should == Count.new(@attribute.bind(derived_relation), nil, @expression)
end
it "returns self if the substituting to the same relation" do
@@ -25,21 +31,15 @@ module Arel
describe '#as' do
it "manufactures an aliased expression" do
- @expression.as(:alias).should == Expression.new(@attribute, "COUNT", :alias, @expression)
+ @expression.as(:alias).should == Expression.new(@attribute, :alias, @expression)
end
end
describe '#to_attribute' do
it "manufactures an attribute with the expression as an ancestor" do
- @expression.to_attribute.should == Attribute.new(@expression.relation, @expression.alias, :ancestor => @expression)
+ @expression.to_attribute(@relation).should == Attribute.new(@relation, @expression.alias, :ancestor => @expression)
end
end
end
-
- describe '#to_sql' do
- it "manufactures sql with the expression and alias" do
- Expression.new(@attribute, "COUNT", :alias).to_sql.should == "COUNT(`users`.`id`) AS `alias`"
- end
- end
end
end
diff --git a/spec/arel/algebra/unit/primitives/value_spec.rb b/spec/arel/algebra/unit/primitives/value_spec.rb
new file mode 100644
index 0000000000..45208e6c5d
--- /dev/null
+++ b/spec/arel/algebra/unit/primitives/value_spec.rb
@@ -0,0 +1,15 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Value do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '#bind' do
+ it "manufactures a new value whose relation is the provided relation" do
+ Value.new(1, @relation).bind(another_relation = Table.new(:photos)).should == Value.new(1, another_relation)
+ end
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/alias_spec.rb b/spec/arel/algebra/unit/relations/alias_spec.rb
new file mode 100644
index 0000000000..a5d716a638
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/alias_spec.rb
@@ -0,0 +1,16 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Alias do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '==' do
+ it "obtains if the objects are the same" do
+ Alias.new(@relation).should_not == Alias.new(@relation)
+ (aliaz = Alias.new(@relation)).should == aliaz
+ end
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/delete_spec.rb b/spec/arel/algebra/unit/relations/delete_spec.rb
new file mode 100644
index 0000000000..7578e12a3e
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/delete_spec.rb
@@ -0,0 +1,9 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Deletion do
+ before do
+ @relation = Table.new(:users)
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/group_spec.rb b/spec/arel/algebra/unit/relations/group_spec.rb
new file mode 100644
index 0000000000..58f9252356
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/group_spec.rb
@@ -0,0 +1,10 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Group do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/insert_spec.rb b/spec/arel/algebra/unit/relations/insert_spec.rb
new file mode 100644
index 0000000000..feb1a5eae4
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/insert_spec.rb
@@ -0,0 +1,9 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Insert do
+ before do
+ @relation = Table.new(:users)
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/join_spec.rb b/spec/arel/algebra/unit/relations/join_spec.rb
new file mode 100644
index 0000000000..f5a8bd32aa
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/join_spec.rb
@@ -0,0 +1,26 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Join do
+ before do
+ @relation1 = Table.new(:users)
+ @relation2 = Table.new(:photos)
+ @predicate = @relation1[:id].eq(@relation2[:user_id])
+ end
+
+ describe 'hashing' do
+ it 'implements hash equality' do
+ InnerJoin.new(@relation1, @relation2, @predicate) \
+ .should hash_the_same_as(InnerJoin.new(@relation1, @relation2, @predicate))
+ end
+ end
+
+ describe '#attributes' do
+ it 'combines the attributes of the two relations' do
+ join = InnerJoin.new(@relation1, @relation2, @predicate)
+ join.attributes.should ==
+ (@relation1.attributes + @relation2.attributes).collect { |a| a.bind(join) }
+ end
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/order_spec.rb b/spec/arel/algebra/unit/relations/order_spec.rb
new file mode 100644
index 0000000000..8b3c932fb9
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/order_spec.rb
@@ -0,0 +1,21 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Order do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe "#==" do
+ it "returns true when the Orders are for the same attribute and direction" do
+ Ascending.new(@attribute).should == Ascending.new(@attribute)
+ end
+
+ it "returns false when the Orders are for a diferent direction" do
+ Ascending.new(@attribute).should_not == Descending.new(@attribute)
+ end
+ end
+ end
+end
+
diff --git a/spec/arel/algebra/unit/relations/project_spec.rb b/spec/arel/algebra/unit/relations/project_spec.rb
new file mode 100644
index 0000000000..9f4358ea54
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/project_spec.rb
@@ -0,0 +1,34 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Project do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe '#attributes' do
+ before do
+ @projection = Project.new(@relation, @attribute)
+ end
+
+ it "manufactures attributes associated with the projection relation" do
+ @projection.attributes.should == [@attribute].collect { |a| a.bind(@projection) }
+ end
+ end
+
+ describe '#externalizable?' do
+ describe 'when the projections are attributes' do
+ it 'returns false' do
+ Project.new(@relation, @attribute).should_not be_externalizable
+ end
+ end
+
+ describe 'when the projections include an aggregation' do
+ it "obtains" do
+ Project.new(@relation, @attribute.sum).should be_externalizable
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/unit/relations/relation_spec.rb b/spec/arel/algebra/unit/relations/relation_spec.rb
index a3bfa67353..adf82847ac 100644
--- a/spec/arel/unit/relations/relation_spec.rb
+++ b/spec/arel/algebra/unit/relations/relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
module Arel
describe Relation do
@@ -34,13 +34,13 @@ module Arel
describe 'when given a relation' do
it "manufactures an inner join operation between those two relations" do
@relation.join(@relation).on(@predicate). \
- should == Join.new("INNER JOIN", @relation, @relation, @predicate)
+ should == InnerJoin.new(@relation, @relation, @predicate)
end
end
describe "when given a string" do
it "manufactures a join operation with the string passed through" do
- @relation.join(arbitrary_string = "ASDF").should == Join.new(arbitrary_string, @relation)
+ @relation.join(arbitrary_string = "ASDF").should == StringJoin.new(@relation, arbitrary_string)
end
end
@@ -54,7 +54,7 @@ module Arel
describe '#outer_join' do
it "manufactures a left outer join operation between those two relations" do
@relation.outer_join(@relation).on(@predicate). \
- should == Join.new("LEFT OUTER JOIN", @relation, @relation, @predicate)
+ should == OuterJoin.new(@relation, @relation, @predicate)
end
end
end
@@ -147,12 +147,31 @@ module Arel
end
describe Relation::Operable::Writable do
+ describe '#delete' do
+ it 'manufactures a deletion relation' do
+ Session.start do
+ mock(Session.new).delete(Deletion.new(@relation))
+ @relation.delete
+ end
+ end
+ end
+
describe '#insert' do
it 'manufactures an insertion relation' do
Session.start do
- record = {@relation[:name] => 'carl'}
+ record = { @relation[:name] => 'carl' }
mock(Session.new).create(Insert.new(@relation, record))
- @relation.insert(record).should == @relation
+ @relation.insert(record)
+ end
+ end
+ end
+
+ describe '#update' do
+ it 'manufactures an update relation' do
+ Session.start do
+ assignments = { @relation[:name] => Value.new('bob', @relation) }
+ mock(Session.new).update(Update.new(@relation, assignments))
+ @relation.update(assignments)
end
end
end
@@ -161,15 +180,8 @@ module Arel
describe Relation::Enumerable do
it "implements enumerable" do
- @relation.collect.should == @relation.session.read(@relation)
- @relation.first.should == @relation.session.read(@relation).first
- end
- end
-
- describe '#call' do
- it 'executes a select_all on the connection' do
- mock(connection = Object.new).execute(@relation.to_sql) { [] }
- @relation.call(connection)
+ @relation.collect.should == @relation.session.read(@relation).collect
+ @relation.first.should == @relation.session.read(@relation).first
end
end
end
diff --git a/spec/arel/algebra/unit/relations/skip_spec.rb b/spec/arel/algebra/unit/relations/skip_spec.rb
new file mode 100644
index 0000000000..a41913436e
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/skip_spec.rb
@@ -0,0 +1,10 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Skip do
+ before do
+ @relation = Table.new(:users)
+ @skipped = 4
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/table_spec.rb b/spec/arel/algebra/unit/relations/table_spec.rb
new file mode 100644
index 0000000000..dfe457043c
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/table_spec.rb
@@ -0,0 +1,39 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Table do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '[]' do
+ describe 'when given a', Symbol do
+ it "manufactures an attribute if the symbol names an attribute within the relation" do
+ @relation[:id].should == Attribute.new(@relation, :id)
+ @relation[:does_not_exist].should be_nil
+ end
+ end
+
+ describe 'when given an', Attribute do
+ it "returns the attribute if the attribute is within the relation" do
+ @relation[@relation[:id]].should == @relation[:id]
+ end
+
+ it "returns nil if the attribtue is not within the relation" do
+ another_relation = Table.new(:photos)
+ @relation[another_relation[:id]].should be_nil
+ end
+ end
+
+ describe 'when given an', Expression do
+ before do
+ @expression = @relation[:id].count
+ end
+
+ it "returns the Expression if the Expression is within the relation" do
+ @relation[@expression].should be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/take_spec.rb b/spec/arel/algebra/unit/relations/take_spec.rb
new file mode 100644
index 0000000000..2bc17db5a1
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/take_spec.rb
@@ -0,0 +1,10 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Take do
+ before do
+ @relation = Table.new(:users)
+ @taken = 4
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/update_spec.rb b/spec/arel/algebra/unit/relations/update_spec.rb
new file mode 100644
index 0000000000..e9642ffc99
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/update_spec.rb
@@ -0,0 +1,9 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Update do
+ before do
+ @relation = Table.new(:users)
+ end
+ end
+end
diff --git a/spec/arel/algebra/unit/relations/where_spec.rb b/spec/arel/algebra/unit/relations/where_spec.rb
new file mode 100644
index 0000000000..6c3074a3a5
--- /dev/null
+++ b/spec/arel/algebra/unit/relations/where_spec.rb
@@ -0,0 +1,18 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Where do
+ before do
+ @relation = Table.new(:users)
+ @predicate = @relation[:id].eq(1)
+ end
+
+ describe '#initialize' do
+ it "manufactures nested where relations if multiple predicates are provided" do
+ another_predicate = @relation[:name].lt(2)
+ Where.new(@relation, @predicate, another_predicate). \
+ should == Where.new(Where.new(@relation, another_predicate), @predicate)
+ end
+ end
+ end
+end
diff --git a/spec/arel/unit/session/session_spec.rb b/spec/arel/algebra/unit/session/session_spec.rb
index 6e73d74f2d..ca0a43f278 100644
--- a/spec/arel/unit/session/session_spec.rb
+++ b/spec/arel/algebra/unit/session/session_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
module Arel
describe Session do
@@ -40,19 +40,19 @@ module Arel
describe '#create' do
it "executes an insertion on the connection" do
- mock(@insert).call(@insert.engine)
+ mock(@insert).call
@session.create(@insert)
end
end
describe '#read' do
it "executes an selection on the connection" do
- mock(@read).call(@read.engine)
+ mock(@read).call
@session.read(@read)
end
it "is memoized" do
- mock(@read).call(@read.engine).once
+ mock(@read).call.once
@session.read(@read)
@session.read(@read)
end
@@ -60,14 +60,14 @@ module Arel
describe '#update' do
it "executes an update on the connection" do
- mock(@update).call(@update.engine)
+ mock(@update).call
@session.update(@update)
end
end
describe '#delete' do
it "executes a delete on the connection" do
- mock(@delete).call(@delete.engine)
+ mock(@delete).call
@session.delete(@delete)
end
end
diff --git a/spec/arel/engines/memory/integration/joins/cross_engine_spec.rb b/spec/arel/engines/memory/integration/joins/cross_engine_spec.rb
new file mode 100644
index 0000000000..bffecc9182
--- /dev/null
+++ b/spec/arel/engines/memory/integration/joins/cross_engine_spec.rb
@@ -0,0 +1,48 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Join do
+ before do
+ @users = Array.new([
+ [1, 'bryan' ],
+ [2, 'emilio' ],
+ [3, 'nick']
+ ], [:id, :name])
+ @photos = Table.new(:photos)
+ @photos.delete
+ @photos \
+ .insert(@photos[:id] => 1, @photos[:user_id] => 1, @photos[:camera_id] => 6) \
+ .insert(@photos[:id] => 2, @photos[:user_id] => 2, @photos[:camera_id] => 42)
+ end
+
+ describe 'when the in memory relation is on the left' do
+ it 'joins across engines' do
+ @users \
+ .join(@photos) \
+ .on(@users[:id].eq(@photos[:user_id])) \
+ .project(@users[:name], @photos[:camera_id]) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, ['bryan', '6']),
+ Row.new(relation, ['emilio', '42'])
+ ]
+ end
+ end
+ end
+
+ describe 'when the in memory relation is on the right' do
+ it 'joins across engines' do
+ @photos \
+ .join(@users) \
+ .on(@users[:id].eq(@photos[:user_id])) \
+ .project(@users[:name], @photos[:camera_id]) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, ['bryan', '6']),
+ Row.new(relation, ['emilio', '42'])
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/array_spec.rb b/spec/arel/engines/memory/unit/relations/array_spec.rb
new file mode 100644
index 0000000000..dd9da41569
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/array_spec.rb
@@ -0,0 +1,32 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Array do
+ before do
+ @relation = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ end
+
+ describe '#attributes' do
+ it 'manufactures attributes corresponding to the names given on construction' do
+ @relation.attributes.should == [
+ Attribute.new(@relation, :id),
+ Attribute.new(@relation, :name)
+ ]
+ end
+ end
+
+ describe '#call' do
+ it "manufactures an array of hashes of attributes to values" do
+ @relation.call.should == [
+ Row.new(@relation, [1, 'duck']),
+ Row.new(@relation, [2, 'duck']),
+ Row.new(@relation, [3, 'goose'])
+ ]
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/insert_spec.rb b/spec/arel/engines/memory/unit/relations/insert_spec.rb
new file mode 100644
index 0000000000..59e43328a3
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/insert_spec.rb
@@ -0,0 +1,28 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Insert do
+ before do
+ @relation = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ end
+
+ describe '#call' do
+ it "manufactures an array of hashes of attributes to values" do
+ @relation \
+ .insert(@relation[:id] => 4, @relation[:name] => 'guinea fowl') \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1, 'duck']),
+ Row.new(relation, [2, 'duck']),
+ Row.new(relation, [3, 'goose']),
+ Row.new(relation, [4, 'guinea fowl'])
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/join_spec.rb b/spec/arel/engines/memory/unit/relations/join_spec.rb
new file mode 100644
index 0000000000..110fdb03b7
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/join_spec.rb
@@ -0,0 +1,31 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Join do
+ before do
+ @relation1 = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ @relation2 = @relation1.alias
+ end
+
+ describe InnerJoin do
+ describe '#call' do
+ it 'combines the two tables where the predicate obtains' do
+ @relation1 \
+ .join(@relation2) \
+ .on(@relation1[:id].eq(@relation2[:id])) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1, 'duck', 1, 'duck' ]),
+ Row.new(relation, [2, 'duck', 2, 'duck' ]),
+ Row.new(relation, [3, 'goose', 3, 'goose'])
+ ]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/order_spec.rb b/spec/arel/engines/memory/unit/relations/order_spec.rb
new file mode 100644
index 0000000000..1e9690bbbf
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/order_spec.rb
@@ -0,0 +1,27 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Order do
+ before do
+ @relation = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ end
+
+ describe '#call' do
+ it 'sorts the relation with the provided ordering' do
+ @relation \
+ .order(@relation[:id].desc) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [3, 'goose']),
+ Row.new(relation, [2, 'duck' ]),
+ Row.new(relation, [1, 'duck' ])
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/project_spec.rb b/spec/arel/engines/memory/unit/relations/project_spec.rb
new file mode 100644
index 0000000000..1690910026
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/project_spec.rb
@@ -0,0 +1,27 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Project do
+ before do
+ @relation = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ end
+
+ describe '#call' do
+ it 'retains only the attributes that are provided' do
+ @relation \
+ .project(@relation[:id]) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1]),
+ Row.new(relation, [2]),
+ Row.new(relation, [3])
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/skip_spec.rb b/spec/arel/engines/memory/unit/relations/skip_spec.rb
new file mode 100644
index 0000000000..3411c5493b
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/skip_spec.rb
@@ -0,0 +1,26 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Skip do
+ before do
+ @relation = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ end
+
+ describe '#call' do
+ it 'removes the first n rows' do
+ @relation \
+ .skip(1) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [2, 'duck']),
+ Row.new(relation, [3, 'goose']),
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/take_spec.rb b/spec/arel/engines/memory/unit/relations/take_spec.rb
new file mode 100644
index 0000000000..5e7c4fb462
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/take_spec.rb
@@ -0,0 +1,26 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Take do
+ before do
+ @relation = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ end
+
+ describe '#call' do
+ it 'removes the rows after the first n' do
+ @relation \
+ .take(2) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1, 'duck']),
+ Row.new(relation, [2, 'duck']),
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/memory/unit/relations/where_spec.rb b/spec/arel/engines/memory/unit/relations/where_spec.rb
new file mode 100644
index 0000000000..1d2c2eb39c
--- /dev/null
+++ b/spec/arel/engines/memory/unit/relations/where_spec.rb
@@ -0,0 +1,39 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Where do
+ before do
+ @relation = Array.new([
+ [1, 'duck' ],
+ [2, 'duck' ],
+ [3, 'goose']
+ ], [:id, :name])
+ end
+
+ describe '#call' do
+ it 'filters the relation with the provided predicate' do
+ @relation \
+ .where(@relation[:id].lt(3)) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1, 'duck']),
+ Row.new(relation, [2, 'duck']),
+ ]
+ end
+ end
+
+ describe 'when filtering a where relation' do
+ it 'further filters the already-filtered relation with the provided predicate' do
+ @relation \
+ .where(@relation[:id].gt(1)) \
+ .where(@relation[:id].lt(3)) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [2, 'duck'])
+ ]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb b/spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb
new file mode 100644
index 0000000000..50b0908441
--- /dev/null
+++ b/spec/arel/engines/sql/integration/joins/with_adjacency_spec.rb
@@ -0,0 +1,209 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Join do
+ before do
+ @relation1 = Table(:users)
+ @relation2 = @relation1.alias
+ @predicate = @relation1[:id].eq(@relation2[:id])
+ end
+
+ describe 'when joining a relation to itself' do
+ describe '#to_sql' do
+ it 'manufactures sql aliasing the table and attributes properly in the join predicate and the where clause' do
+ sql = @relation1.join(@relation2).on(@predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
+ FROM `users`
+ INNER JOIN `users` AS `users_2`
+ ON `users`.`id` = `users_2`.`id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
+ FROM "users"
+ INNER JOIN "users" AS "users_2"
+ ON "users"."id" = "users_2"."id"
+ })
+ end
+ end
+
+ describe 'when joining with a where on the same relation' do
+ it 'manufactures sql aliasing the tables properly' do
+ sql = @relation1 \
+ .join(@relation2.where(@relation2[:id].eq(1))) \
+ .on(@predicate) \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
+ FROM `users`
+ INNER JOIN `users` AS `users_2`
+ ON `users`.`id` = `users_2`.`id` AND `users_2`.`id` = 1
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
+ FROM "users"
+ INNER JOIN "users" AS "users_2"
+ ON "users"."id" = "users_2"."id" AND "users_2"."id" = 1
+ })
+ end
+ end
+
+ describe 'when the where occurs before the alias' do
+ it 'manufactures sql aliasing the predicates properly' do
+ relation2 = @relation1.where(@relation1[:id].eq(1)).alias
+
+ sql = @relation1 \
+ .join(relation2) \
+ .on(relation2[:id].eq(@relation1[:id])) \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
+ FROM `users`
+ INNER JOIN `users` AS `users_2`
+ ON `users_2`.`id` = `users`.`id` AND `users_2`.`id` = 1
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name"
+ FROM "users"
+ INNER JOIN "users" AS "users_2"
+ ON "users_2"."id" = "users"."id" AND "users_2"."id" = 1
+ })
+ end
+ end
+ end
+ end
+
+ describe 'when joining the relation to itself multiple times' do
+ before do
+ @relation3 = @relation1.alias
+ end
+
+ describe 'when joining left-associatively' do
+ it 'manufactures sql aliasing the tables properly' do
+ sql = @relation1 \
+ .join(@relation2 \
+ .join(@relation3) \
+ .on(@relation2[:id].eq(@relation3[:id]))) \
+ .on(@relation1[:id].eq(@relation2[:id])) \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
+ FROM `users`
+ INNER JOIN `users` AS `users_2`
+ ON `users`.`id` = `users_2`.`id`
+ INNER JOIN `users` AS `users_3`
+ ON `users_2`.`id` = `users_3`.`id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name", "users_3"."id", "users_3"."name"
+ FROM "users"
+ INNER JOIN "users" AS "users_2"
+ ON "users"."id" = "users_2"."id"
+ INNER JOIN "users" AS "users_3"
+ ON "users_2"."id" = "users_3"."id"
+ })
+ end
+ end
+ end
+
+ describe 'when joining right-associatively' do
+ it 'manufactures sql aliasing the tables properly' do
+ sql = @relation1 \
+ .join(@relation2).on(@relation1[:id].eq(@relation2[:id])) \
+ .join(@relation3).on(@relation2[:id].eq(@relation3[:id])) \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
+ FROM `users`
+ INNER JOIN `users` AS `users_2`
+ ON `users`.`id` = `users_2`.`id`
+ INNER JOIN `users` AS `users_3`
+ ON `users_2`.`id` = `users_3`.`id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "users_2"."id", "users_2"."name", "users_3"."id", "users_3"."name"
+ FROM "users"
+ INNER JOIN "users" AS "users_2"
+ ON "users"."id" = "users_2"."id"
+ INNER JOIN "users" AS "users_3"
+ ON "users_2"."id" = "users_3"."id"
+ })
+ end
+ end
+ end
+ end
+ end
+
+ describe '[]' do
+ describe 'when given an attribute belonging to both sub-relations' do
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
+ @relation1 \
+ .join(@relation2) \
+ .on(@predicate) \
+ .should disambiguate_attributes(@relation1[:id], @relation2[:id])
+ end
+
+ describe 'when both relations are compound and only one is an alias' do
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
+ compound1 = @relation1.where(@predicate)
+ compound2 = compound1.alias
+ compound1 \
+ .join(compound2) \
+ .on(@predicate) \
+ .should disambiguate_attributes(compound1[:id], compound2[:id])
+ end
+ end
+
+ describe 'when the left relation is extremely compound' do
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
+ @relation1 \
+ .where(@predicate) \
+ .where(@predicate) \
+ .join(@relation2) \
+ .on(@predicate) \
+ .should disambiguate_attributes(@relation1[:id], @relation2[:id])
+ end
+ end
+
+ describe 'when the right relation is extremely compound' do
+ it 'disambiguates the relation that serves as the ancestor to the attribute' do
+ @relation1 \
+ .join( \
+ @relation2 \
+ .where(@predicate) \
+ .where(@predicate) \
+ .where(@predicate)) \
+ .on(@predicate) \
+ .should disambiguate_attributes(@relation1[:id], @relation2[:id])
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb b/spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb
new file mode 100644
index 0000000000..709ae9f8d1
--- /dev/null
+++ b/spec/arel/engines/sql/integration/joins/with_aggregations_spec.rb
@@ -0,0 +1,167 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Join do
+ before do
+ @relation1 = Table(:users)
+ @relation2 = Table(:photos)
+ @predicate = @relation1[:id].eq(@relation2[:user_id])
+ end
+
+ describe 'when joining aggregated relations' do
+ before do
+ @aggregation = @relation2 \
+ .group(@relation2[:user_id]) \
+ .project(@relation2[:user_id], @relation2[:id].count.as(:cnt)) \
+ end
+
+ describe '#to_sql' do
+ # CLEANUP
+ it '' do
+ sql = @relation1.join(@relation2.take(3)).on(@predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `photos_external`.`id`, `photos_external`.`user_id`, `photos_external`.`camera_id`
+ FROM `users`
+ INNER JOIN (SELECT `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id` FROM `photos` LIMIT 3) AS `photos_external`
+ ON `users`.`id` = `photos_external`.`user_id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "photos_external"."id", "photos_external"."user_id", "photos_external"."camera_id"
+ FROM "users"
+ INNER JOIN (SELECT "photos"."id", "photos"."user_id", "photos"."camera_id" FROM "photos" LIMIT 3) AS "photos_external"
+ ON "users"."id" = "photos_external"."user_id"
+ })
+ end
+ end
+
+ describe 'with the aggregation on the right' do
+ it 'manufactures sql joining the left table to a derived table' do
+ sql = @relation1.join(@aggregation).on(@predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `photos_external`.`user_id`, `photos_external`.`cnt`
+ FROM `users`
+ INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
+ ON `users`.`id` = `photos_external`.`user_id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "photos_external"."user_id", "photos_external"."cnt"
+ FROM "users"
+ INNER JOIN (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external"
+ ON "users"."id" = "photos_external"."user_id"
+ })
+ end
+ end
+ end
+
+ describe 'with the aggregation on the left' do
+ it 'manufactures sql joining the right table to a derived table' do
+ sql = @aggregation.join(@relation1).on(@predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `users`.`id`, `users`.`name`
+ FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
+ INNER JOIN `users`
+ ON `users`.`id` = `photos_external`.`user_id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "photos_external"."user_id", "photos_external"."cnt", "users"."id", "users"."name"
+ FROM (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external"
+ INNER JOIN "users"
+ ON "users"."id" = "photos_external"."user_id"
+ })
+ end
+ end
+ end
+
+ describe 'with the aggregation on both sides' do
+ it 'it properly aliases the aggregations' do
+ aggregation2 = @aggregation.alias
+ sql = @aggregation.join(aggregation2).on(aggregation2[:user_id].eq(@aggregation[:user_id])).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `photos_external_2`.`user_id`, `photos_external_2`.`cnt`
+ FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
+ INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external_2`
+ ON `photos_external_2`.`user_id` = `photos_external`.`user_id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "photos_external"."user_id", "photos_external"."cnt", "photos_external_2"."user_id", "photos_external_2"."cnt"
+ FROM (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external"
+ INNER JOIN (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" GROUP BY "photos"."user_id") AS "photos_external_2"
+ ON "photos_external_2"."user_id" = "photos_external"."user_id"
+ })
+ end
+ end
+ end
+
+ describe 'when the aggration has a where' do
+ describe 'with the aggregation on the left' do
+ it "manufactures sql keeping wheres on the aggregation within the derived table" do
+ sql = @relation1.join(@aggregation.where(@aggregation[:user_id].eq(1))).on(@predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `photos_external`.`user_id`, `photos_external`.`cnt`
+ FROM `users`
+ INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` WHERE `photos`.`user_id` = 1 GROUP BY `photos`.`user_id`) AS `photos_external`
+ ON `users`.`id` = `photos_external`.`user_id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "photos_external"."user_id", "photos_external"."cnt"
+ FROM "users"
+ INNER JOIN (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" WHERE "photos"."user_id" = 1 GROUP BY "photos"."user_id") AS "photos_external"
+ ON "users"."id" = "photos_external"."user_id"
+ })
+ end
+ end
+ end
+
+ describe 'with the aggregation on the right' do
+ it "manufactures sql keeping wheres on the aggregation within the derived table" do
+ sql = @aggregation.where(@aggregation[:user_id].eq(1)).join(@relation1).on(@predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `users`.`id`, `users`.`name`
+ FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` WHERE `photos`.`user_id` = 1 GROUP BY `photos`.`user_id`) AS `photos_external`
+ INNER JOIN `users`
+ ON `users`.`id` = `photos_external`.`user_id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "photos_external"."user_id", "photos_external"."cnt", "users"."id", "users"."name"
+ FROM (SELECT "photos"."user_id", COUNT("photos"."id") AS "cnt" FROM "photos" WHERE "photos"."user_id" = 1 GROUP BY "photos"."user_id") AS "photos_external"
+ INNER JOIN "users"
+ ON "users"."id" = "photos_external"."user_id"
+ })
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/integration/joins/with_compounds_spec.rb b/spec/arel/engines/sql/integration/joins/with_compounds_spec.rb
new file mode 100644
index 0000000000..4bceef4975
--- /dev/null
+++ b/spec/arel/engines/sql/integration/joins/with_compounds_spec.rb
@@ -0,0 +1,107 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Join do
+ before do
+ @relation1 = Table(:users)
+ @relation2 = Table(:photos)
+ @predicate = @relation1[:id].eq(@relation2[:user_id])
+ end
+
+ describe '#to_sql' do
+ describe 'when the join contains a where' do
+ describe 'and the where is given a string' do
+ it 'does not escape the string' do
+ sql = @relation1 \
+ .join(@relation2.where("asdf")) \
+ .on(@predicate) \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
+ FROM `users`
+ INNER JOIN `photos`
+ ON `users`.`id` = `photos`.`user_id` AND asdf
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "photos"."id", "photos"."user_id", "photos"."camera_id"
+ FROM "users"
+ INNER JOIN "photos"
+ ON "users"."id" = "photos"."user_id" AND asdf
+ })
+ end
+ end
+ end
+ end
+
+ describe 'when a compound contains a join' do
+ describe 'and the compound is a where' do
+ it 'manufactures sql disambiguating the tables' do
+ sql = @relation1 \
+ .where(@relation1[:id].eq(1)) \
+ .join(@relation2) \
+ .on(@predicate) \
+ .where(@relation1[:id].eq(1)) \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
+ FROM `users`
+ INNER JOIN `photos`
+ ON `users`.`id` = `photos`.`user_id`
+ WHERE `users`.`id` = 1
+ AND `users`.`id` = 1
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "photos"."id", "photos"."user_id", "photos"."camera_id"
+ FROM "users"
+ INNER JOIN "photos"
+ ON "users"."id" = "photos"."user_id"
+ WHERE "users"."id" = 1
+ AND "users"."id" = 1
+ })
+ end
+ end
+ end
+
+ describe 'and the compound is a group' do
+ it 'manufactures sql disambiguating the tables' do
+ sql = @relation1 \
+ .join(@relation2) \
+ .on(@predicate) \
+ .group(@relation1[:id]) \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
+ FROM `users`
+ INNER JOIN `photos`
+ ON `users`.`id` = `photos`.`user_id`
+ GROUP BY `users`.`id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "photos"."id", "photos"."user_id", "photos"."camera_id"
+ FROM "users"
+ INNER JOIN "photos"
+ ON "users"."id" = "photos"."user_id"
+ GROUP BY "users"."id"
+ })
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/engine_spec.rb b/spec/arel/engines/sql/unit/engine_spec.rb
new file mode 100644
index 0000000000..c607abcfa1
--- /dev/null
+++ b/spec/arel/engines/sql/unit/engine_spec.rb
@@ -0,0 +1,45 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Sql::Engine do
+ before do
+ @users = Table.new(:users)
+ @users.delete
+ end
+
+ describe "CRUD" do
+ describe "#create" do
+ it "inserts into the relation" do
+ @users.insert @users[:name] => "Bryan"
+ @users.first[@users[:name]].should == "Bryan"
+ end
+ end
+
+ describe "#read" do
+ it "reads from the relation" do
+ @users.insert @users[:name] => "Bryan"
+
+ @users.each do |row|
+ row[@users[:name]].should == "Bryan"
+ end
+ end
+ end
+
+ describe "#update" do
+ it "updates the relation" do
+ @users.insert @users[:name] => "Nick"
+ @users.update @users[:name] => "Bryan"
+ @users.first[@users[:name]].should == "Bryan"
+ end
+ end
+
+ describe "#delete" do
+ it "deletes from the relation" do
+ @users.insert @users[:name] => "Bryan"
+ @users.delete
+ @users.first.should == nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/predicates/binary_spec.rb b/spec/arel/engines/sql/unit/predicates/binary_spec.rb
new file mode 100644
index 0000000000..b1400e2588
--- /dev/null
+++ b/spec/arel/engines/sql/unit/predicates/binary_spec.rb
@@ -0,0 +1,117 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Binary do
+ before do
+ @relation = Table.new(:users)
+ @attribute1 = @relation[:id]
+ @attribute2 = @relation[:name]
+ class ConcreteBinary < Binary
+ def predicate_sql
+ "<=>"
+ end
+ end
+ end
+
+ describe "with compound predicates" do
+ before do
+ @operand1 = ConcreteBinary.new(@attribute1, 1)
+ @operand2 = ConcreteBinary.new(@attribute2, "name")
+ end
+
+ describe Or do
+ describe "#to_sql" do
+ it "manufactures sql with an OR operation" do
+ sql = Or.new(@operand1, @operand2).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{(`users`.`id` <=> 1 OR `users`.`name` <=> 'name')})
+ end
+
+ adapter_is :postgresql do
+ sql.should be_like(%Q{("users"."id" <=> 1 OR "users"."name" <=> E'name')})
+ end
+
+ adapter_is :sqlite3 do
+ sql.should be_like(%Q{("users"."id" <=> 1 OR "users"."name" <=> 'name')})
+ end
+ end
+ end
+ end
+
+ describe And do
+ describe "#to_sql" do
+ it "manufactures sql with an AND operation" do
+ sql = And.new(@operand1, @operand2).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{(`users`.`id` <=> 1 AND `users`.`name` <=> 'name')})
+ end
+
+ adapter_is :sqlite3 do
+ sql.should be_like(%Q{("users"."id" <=> 1 AND "users"."name" <=> 'name')})
+ end
+
+ adapter_is :postgresql do
+ sql.should be_like(%Q{("users"."id" <=> 1 AND "users"."name" <=> E'name')})
+ end
+ end
+ end
+ end
+ end
+
+ describe '#to_sql' do
+ describe 'when relating two attributes' do
+ it 'manufactures sql with a binary operation' do
+ sql = ConcreteBinary.new(@attribute1, @attribute2).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id` <=> `users`.`name`})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id" <=> "users"."name"})
+ end
+ end
+ end
+
+ describe 'when relating an attribute and a value' do
+ before do
+ @value = "1-asdf"
+ end
+
+ describe 'when relating to an integer attribute' do
+ it 'formats values as integers' do
+ sql = ConcreteBinary.new(@attribute1, @value).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id` <=> 1})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id" <=> 1})
+ end
+ end
+ end
+
+ describe 'when relating to a string attribute' do
+ it 'formats values as strings' do
+ sql = ConcreteBinary.new(@attribute2, @value).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`name` <=> '1-asdf'})
+ end
+
+ adapter_is :sqlite3 do
+ sql.should be_like(%Q{"users"."name" <=> '1-asdf'})
+ end
+
+ adapter_is :postgresql do
+ sql.should be_like(%Q{"users"."name" <=> E'1-asdf'})
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/predicates/equality_spec.rb b/spec/arel/engines/sql/unit/predicates/equality_spec.rb
new file mode 100644
index 0000000000..688a6a20be
--- /dev/null
+++ b/spec/arel/engines/sql/unit/predicates/equality_spec.rb
@@ -0,0 +1,46 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Equality do
+ before do
+ @relation1 = Table.new(:users)
+ @relation2 = Table.new(:photos)
+ @attribute1 = @relation1[:id]
+ @attribute2 = @relation2[:user_id]
+ end
+
+ describe '#to_sql' do
+ describe 'when relating to a non-nil value' do
+ it "manufactures an equality predicate" do
+ sql = Equality.new(@attribute1, @attribute2).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id` = `photos`.`user_id`})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id" = "photos"."user_id"})
+ end
+ end
+ end
+
+ describe 'when relation to a nil value' do
+ before do
+ @nil = nil
+ end
+
+ it "manufactures an is null predicate" do
+ sql = Equality.new(@attribute1, @nil).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id` IS NULL})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id" IS NULL})
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/predicates/in_spec.rb b/spec/arel/engines/sql/unit/predicates/in_spec.rb
new file mode 100644
index 0000000000..d3e75cfb84
--- /dev/null
+++ b/spec/arel/engines/sql/unit/predicates/in_spec.rb
@@ -0,0 +1,86 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe In do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe '#to_sql' do
+ describe 'when relating to an array' do
+ describe 'when the array\'s elements are the same type as the attribute' do
+ before do
+ @array = [1, 2, 3]
+ end
+
+ it 'manufactures sql with a comma separated list' do
+ sql = In.new(@attribute, @array).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id` IN (1, 2, 3)})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id" IN (1, 2, 3)})
+ end
+ end
+ end
+
+ describe 'when the array\'s elements are not same type as the attribute' do
+ before do
+ @array = ['1-asdf', 2, 3]
+ end
+
+ it 'formats values in the array as the type of the attribute' do
+ sql = In.new(@attribute, @array).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id` IN (1, 2, 3)})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id" IN (1, 2, 3)})
+ end
+ end
+ end
+ end
+
+ describe 'when relating to a range' do
+ before do
+ @range = 1..2
+ end
+
+ it 'manufactures sql with a between' do
+ sql = In.new(@attribute, @range).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id` BETWEEN 1 AND 2})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id" BETWEEN 1 AND 2})
+ end
+ end
+ end
+
+ describe 'when relating to a relation' do
+ it 'manufactures sql with a subselect' do
+ sql = In.new(@attribute, @relation).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ `users`.`id` IN (SELECT `users`.`id`, `users`.`name` FROM `users`)
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ "users"."id" IN (SELECT "users"."id", "users"."name" FROM "users")
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/predicates/predicates_spec.rb b/spec/arel/engines/sql/unit/predicates/predicates_spec.rb
new file mode 100644
index 0000000000..d55e178e43
--- /dev/null
+++ b/spec/arel/engines/sql/unit/predicates/predicates_spec.rb
@@ -0,0 +1,65 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Predicate do
+ before do
+ @relation = Table.new(:users)
+ @attribute1 = @relation[:id]
+ @attribute2 = @relation[:name]
+ @operand1 = Equality.new(@attribute1, 1)
+ @operand2 = Equality.new(@attribute2, "name")
+ end
+
+ describe "when being combined with another predicate with AND logic" do
+ describe "#to_sql" do
+ it "manufactures sql with an AND operation" do
+ sql = @operand1.and(@operand2).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ (`users`.`id` = 1 AND `users`.`name` = 'name')
+ })
+ end
+
+ adapter_is :sqlite3 do
+ sql.should be_like(%Q{
+ ("users"."id" = 1 AND "users"."name" = 'name')
+ })
+ end
+
+ adapter_is :postgresql do
+ sql.should be_like(%Q{
+ ("users"."id" = 1 AND "users"."name" = E'name')
+ })
+ end
+ end
+ end
+ end
+
+ describe "when being combined with another predicate with OR logic" do
+ describe "#to_sql" do
+ it "manufactures sql with an OR operation" do
+ sql = @operand1.or(@operand2).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ (`users`.`id` = 1 OR `users`.`name` = 'name')
+ })
+ end
+
+ adapter_is :sqlite3 do
+ sql.should be_like(%Q{
+ ("users"."id" = 1 OR "users"."name" = 'name')
+ })
+ end
+
+ adapter_is :postgresql do
+ sql.should be_like(%Q{
+ ("users"."id" = 1 OR "users"."name" = E'name')
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/primitives/attribute_spec.rb b/spec/arel/engines/sql/unit/primitives/attribute_spec.rb
new file mode 100644
index 0000000000..6cb72f3c19
--- /dev/null
+++ b/spec/arel/engines/sql/unit/primitives/attribute_spec.rb
@@ -0,0 +1,32 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Attribute do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe '#column' do
+ it "returns the corresponding column in the relation" do
+ @attribute.column.should == @relation.column_for(@attribute)
+ end
+ end
+
+ describe '#to_sql' do
+ describe 'for a simple attribute' do
+ it "manufactures sql with an alias" do
+ sql = @attribute.to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{`users`.`id`})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{"users"."id"})
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/primitives/expression_spec.rb b/spec/arel/engines/sql/unit/primitives/expression_spec.rb
new file mode 100644
index 0000000000..ee7f2c1461
--- /dev/null
+++ b/spec/arel/engines/sql/unit/primitives/expression_spec.rb
@@ -0,0 +1,24 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Expression do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe '#to_sql' do
+ it "manufactures sql with the expression and alias" do
+ sql = Count.new(@attribute, :alias).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{COUNT(`users`.`id`) AS `alias`})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{COUNT("users"."id") AS "alias"})
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/primitives/literal_spec.rb b/spec/arel/engines/sql/unit/primitives/literal_spec.rb
new file mode 100644
index 0000000000..c7ff1cf879
--- /dev/null
+++ b/spec/arel/engines/sql/unit/primitives/literal_spec.rb
@@ -0,0 +1,23 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe SqlLiteral do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '#to_sql' do
+ it "manufactures sql with a literal SQL fragment" do
+ sql = @relation.project(Count.new(SqlLiteral.new("*"))).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{SELECT COUNT(*) AS count_id FROM `users`})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{SELECT COUNT(*) AS count_id FROM "users"})
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/unit/primitives/value_spec.rb b/spec/arel/engines/sql/unit/primitives/value_spec.rb
index ba9a80bb49..ff3533f6ef 100644
--- a/spec/arel/unit/primitives/value_spec.rb
+++ b/spec/arel/engines/sql/unit/primitives/value_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
module Arel
describe Value do
@@ -9,7 +9,14 @@ module Arel
describe '#to_sql' do
it "appropriately quotes the value" do
Value.new(1, @relation).to_sql.should be_like('1')
- Value.new('asdf', @relation).to_sql.should be_like("'asdf'")
+
+ adapter_is_not :postgresql do
+ Value.new('asdf', @relation).to_sql.should be_like("'asdf'")
+ end
+
+ adapter_is :postgresql do
+ Value.new('asdf', @relation).to_sql.should be_like("E'asdf'")
+ end
end
end
@@ -18,11 +25,5 @@ module Arel
Value.new(1, @relation).format(@relation[:id]).should == @relation[:id].to_sql
end
end
-
- describe '#bind' do
- it "manufactures a new value whose relation is the provided relation" do
- Value.new(1, @relation).bind(another_relation = Table.new(:photos)).should == Value.new(1, another_relation)
- end
- end
end
end
diff --git a/spec/arel/engines/sql/unit/relations/alias_spec.rb b/spec/arel/engines/sql/unit/relations/alias_spec.rb
new file mode 100644
index 0000000000..b67a0bbc89
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/alias_spec.rb
@@ -0,0 +1,43 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Alias do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '#to_sql' do
+ describe 'when there is no ambiguity' do
+ it 'does not alias table names anywhere a table name can appear' do
+ sql = @relation \
+ .where(@relation[:id].eq(1)) \
+ .order(@relation[:id]) \
+ .project(@relation[:id]) \
+ .group(@relation[:id]) \
+ .alias \
+ .to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`
+ FROM `users`
+ WHERE `users`.`id` = 1
+ GROUP BY `users`.`id`
+ ORDER BY `users`.`id` ASC
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id"
+ FROM "users"
+ WHERE "users"."id" = 1
+ GROUP BY "users"."id"
+ ORDER BY "users"."id" ASC
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/delete_spec.rb b/spec/arel/engines/sql/unit/relations/delete_spec.rb
new file mode 100644
index 0000000000..7a5e2b0088
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/delete_spec.rb
@@ -0,0 +1,63 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Deletion do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '#to_sql' do
+ it 'manufactures sql deleting a table relation' do
+ sql = Deletion.new(@relation).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{DELETE FROM `users`})
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{DELETE FROM "users"})
+ end
+ end
+
+ it 'manufactures sql deleting a where relation' do
+ sql = Deletion.new(@relation.where(@relation[:id].eq(1))).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ DELETE
+ FROM `users`
+ WHERE `users`.`id` = 1
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ DELETE
+ FROM "users"
+ WHERE "users"."id" = 1
+ })
+ end
+ end
+
+ it "manufactures sql deleting a ranged relation" do
+ sql = Deletion.new(@relation.take(1)).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ DELETE
+ FROM `users`
+ LIMIT 1
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ DELETE
+ FROM "users"
+ LIMIT 1
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/group_spec.rb b/spec/arel/engines/sql/unit/relations/group_spec.rb
new file mode 100644
index 0000000000..5e0c675c8b
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/group_spec.rb
@@ -0,0 +1,56 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Group do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe '#to_sql' do
+ describe 'when given a predicate' do
+ it "manufactures sql with where clause conditions" do
+ sql = Group.new(@relation, @attribute).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ GROUP BY `users`.`id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ GROUP BY "users"."id"
+ })
+ end
+ end
+ end
+
+ describe 'when given a string' do
+ it "passes the string through to the where clause" do
+ sql = Group.new(@relation, 'asdf').to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ GROUP BY asdf
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ GROUP BY asdf
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/insert_spec.rb b/spec/arel/engines/sql/unit/relations/insert_spec.rb
new file mode 100644
index 0000000000..29a5e0bf42
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/insert_spec.rb
@@ -0,0 +1,107 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Insert do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '#to_sql' do
+ it 'manufactures sql inserting data when given multiple rows' do
+ pending 'it should insert multiple rows' do
+ @insertion = Insert.new(@relation, [@relation[:name] => "nick", @relation[:name] => "bryan"])
+
+ @insertion.to_sql.should be_like("
+ INSERT
+ INTO `users`
+ (`name`) VALUES ('nick'), ('bryan')
+ ")
+ end
+ end
+
+ it 'manufactures sql inserting data when given multiple values' do
+ @insertion = Insert.new(@relation, @relation[:id] => "1", @relation[:name] => "nick")
+
+ adapter_is :mysql do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO `users`
+ (`id`, `name`) VALUES (1, 'nick')
+ })
+ end
+
+ adapter_is :sqlite3 do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO "users"
+ ("id", "name") VALUES (1, 'nick')
+ })
+ end
+
+ adapter_is :postgresql do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO "users"
+ ("id", "name") VALUES (1, E'nick')
+ })
+ end
+ end
+
+ describe 'when given values whose types correspond to the types of the attributes' do
+ before do
+ @insertion = Insert.new(@relation, @relation[:name] => "nick")
+ end
+
+ it 'manufactures sql inserting data' do
+ adapter_is :mysql do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO `users`
+ (`name`) VALUES ('nick')
+ })
+ end
+
+ adapter_is :sqlite3 do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO "users"
+ ("name") VALUES ('nick')
+ })
+ end
+
+ adapter_is :postgresql do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO "users"
+ ("name") VALUES (E'nick')
+ })
+ end
+ end
+ end
+
+ describe 'when given values whose types differ from from the types of the attributes' do
+ before do
+ @insertion = Insert.new(@relation, @relation[:id] => '1-asdf')
+ end
+
+ it 'manufactures sql inserting data' do
+ adapter_is :mysql do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO `users`
+ (`id`) VALUES (1)
+ })
+ end
+
+ adapter_is_not :mysql do
+ @insertion.to_sql.should be_like(%Q{
+ INSERT
+ INTO "users"
+ ("id") VALUES (1)
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/join_spec.rb b/spec/arel/engines/sql/unit/relations/join_spec.rb
new file mode 100644
index 0000000000..f904b61870
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/join_spec.rb
@@ -0,0 +1,57 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Join do
+ before do
+ @relation1 = Table.new(:users)
+ @relation2 = Table.new(:photos)
+ @predicate = @relation1[:id].eq(@relation2[:user_id])
+ end
+
+ describe '#to_sql' do
+ describe 'when joining with another relation' do
+ it 'manufactures sql joining the two tables on the predicate' do
+ sql = InnerJoin.new(@relation1, @relation2, @predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
+ FROM `users`
+ INNER JOIN `photos` ON `users`.`id` = `photos`.`user_id`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name", "photos"."id", "photos"."user_id", "photos"."camera_id"
+ FROM "users"
+ INNER JOIN "photos" ON "users"."id" = "photos"."user_id"
+ })
+ end
+ end
+ end
+
+ describe 'when joining with a string' do
+ it "passes the string through to the where clause" do
+ sql = StringJoin.new(@relation1, "INNER JOIN asdf ON fdsa").to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ INNER JOIN asdf ON fdsa
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ INNER JOIN asdf ON fdsa
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/order_spec.rb b/spec/arel/engines/sql/unit/relations/order_spec.rb
new file mode 100644
index 0000000000..ce97a4dd5e
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/order_spec.rb
@@ -0,0 +1,113 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Order do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe '#to_sql' do
+ describe "when given an attribute" do
+ it "manufactures sql with an order clause populated by the attribute" do
+ sql = Order.new(@relation, @attribute).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ ORDER BY `users`.`id` ASC
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ ORDER BY "users"."id" ASC
+ })
+ end
+ end
+ end
+
+ describe "when given multiple attributes" do
+ before do
+ @another_attribute = @relation[:name]
+ end
+
+ it "manufactures sql with an order clause populated by comma-separated attributes" do
+ sql = Order.new(@relation, @attribute, @another_attribute).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ ORDER BY `users`.`id` ASC, `users`.`name` ASC
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ ORDER BY "users"."id" ASC, "users"."name" ASC
+ })
+ end
+ end
+ end
+
+ describe "when given a string" do
+ before do
+ @string = "asdf"
+ end
+
+ it "passes the string through to the order clause" do
+ sql = Order.new(@relation, @string).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ ORDER BY asdf
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ ORDER BY asdf
+ })
+ end
+ end
+ end
+
+ describe "when ordering an ordered relation" do
+ before do
+ @ordered_relation = Order.new(@relation, @attribute)
+ @another_attribute = @relation[:name]
+ end
+
+ it "manufactures sql with the order clause of the last ordering preceding the first ordering" do
+ sql = Order.new(@ordered_relation, @another_attribute).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ ORDER BY `users`.`name` ASC, `users`.`id` ASC
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ ORDER BY "users"."name" ASC, "users"."id" ASC
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/project_spec.rb b/spec/arel/engines/sql/unit/relations/project_spec.rb
new file mode 100644
index 0000000000..5e29124cfa
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/project_spec.rb
@@ -0,0 +1,110 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Project do
+ before do
+ @relation = Table.new(:users)
+ @attribute = @relation[:id]
+ end
+
+ describe '#to_sql' do
+ describe 'when given an attribute' do
+ it "manufactures sql with a limited select clause" do
+ sql = Project.new(@relation, @attribute).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`
+ FROM `users`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id"
+ FROM "users"
+ })
+ end
+ end
+ end
+
+ describe 'when given a relation' do
+ before do
+ @scalar_relation = Project.new(@relation, @relation[:name])
+ end
+
+ it "manufactures sql with scalar selects" do
+ sql = Project.new(@relation, @scalar_relation).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT (SELECT `users`.`name` FROM `users`) AS `users` FROM `users`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT (SELECT "users"."name" FROM "users") AS "users" FROM "users"
+ })
+ end
+ end
+ end
+
+ describe 'when given a string' do
+ it "passes the string through to the select clause" do
+ sql = Project.new(@relation, 'asdf').to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT asdf FROM `users`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT asdf FROM "users"
+ })
+ end
+ end
+ end
+
+ describe 'when given an expression' do
+ it 'manufactures sql with expressions' do
+ sql = @relation.project(@attribute.count).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT COUNT(`users`.`id`) AS count_id
+ FROM `users`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT COUNT("users"."id") AS count_id
+ FROM "users"
+ })
+ end
+ end
+
+ it 'manufactures sql with distinct expressions' do
+ sql = @relation.project(@attribute.count(true)).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT COUNT(DISTINCT `users`.`id`) AS count_id
+ FROM `users`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT COUNT(DISTINCT "users"."id") AS count_id
+ FROM "users"
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/skip_spec.rb b/spec/arel/engines/sql/unit/relations/skip_spec.rb
new file mode 100644
index 0000000000..c14bd1ce95
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/skip_spec.rb
@@ -0,0 +1,32 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Skip do
+ before do
+ @relation = Table.new(:users)
+ @skipped = 4
+ end
+
+ describe '#to_sql' do
+ it "manufactures sql with limit and offset" do
+ sql = Skip.new(@relation, @skipped).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ OFFSET 4
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ OFFSET 4
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/table_spec.rb b/spec/arel/engines/sql/unit/relations/table_spec.rb
new file mode 100644
index 0000000000..9797b38822
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/table_spec.rb
@@ -0,0 +1,69 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Table do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '#to_sql' do
+ it "manufactures a simple select query" do
+ sql = @relation.to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ })
+ end
+ end
+ end
+
+ describe '#column_for' do
+ it "returns the column corresponding to the attribute" do
+ @relation.column_for(@relation[:id]).should == @relation.columns.detect { |c| c.name == 'id' }
+ end
+ end
+
+ describe '#attributes' do
+ it 'manufactures attributes corresponding to columns in the table' do
+ @relation.attributes.should == [
+ Attribute.new(@relation, :id),
+ Attribute.new(@relation, :name)
+ ]
+ end
+
+ describe '#reset' do
+ it "reloads columns from the database" do
+ lambda { stub(@relation.engine).columns { [] } }.should_not change { @relation.attributes }
+ lambda { @relation.reset }.should change { @relation.attributes }
+ end
+ end
+ end
+
+ describe 'hashing' do
+ it "implements hash equality" do
+ Table.new(:users).should hash_the_same_as(Table.new(:users))
+ Table.new(:users).should_not hash_the_same_as(Table.new(:photos))
+ end
+ end
+
+ describe '#engine' do
+ it "defaults to global engine" do
+ Table.engine = engine = Sql::Engine.new
+ Table.new(:users).engine.should == engine
+ end
+
+ it "can be specified" do
+ Table.new(:users, engine = Sql::Engine.new).engine.should == engine
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/take_spec.rb b/spec/arel/engines/sql/unit/relations/take_spec.rb
new file mode 100644
index 0000000000..8f1240fc17
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/take_spec.rb
@@ -0,0 +1,32 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Take do
+ before do
+ @relation = Table.new(:users)
+ @taken = 4
+ end
+
+ describe '#to_sql' do
+ it "manufactures sql with limit and offset" do
+ sql = Take.new(@relation, @taken).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ LIMIT 4
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ LIMIT 4
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/update_spec.rb b/spec/arel/engines/sql/unit/relations/update_spec.rb
new file mode 100644
index 0000000000..4d728eb241
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/update_spec.rb
@@ -0,0 +1,151 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Update do
+ before do
+ @relation = Table.new(:users)
+ end
+
+ describe '#to_sql' do
+ it "manufactures sql updating attributes when given multiple attributes" do
+ sql = Update.new(@relation, @relation[:id] => 1, @relation[:name] => "nick").to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ UPDATE `users`
+ SET `id` = 1, `name` = 'nick'
+ })
+ end
+
+ adapter_is :sqlite3 do
+ sql.should be_like(%Q{
+ UPDATE "users"
+ SET "id" = 1, "name" = 'nick'
+ })
+ end
+
+ adapter_is :postgresql do
+ sql.should be_like(%Q{
+ UPDATE "users"
+ SET "id" = 1, "name" = E'nick'
+ })
+ end
+ end
+
+ it "manufactures sql updating attributes when given a ranged relation" do
+ sql = Update.new(@relation.take(1), @relation[:name] => "nick").to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ UPDATE `users`
+ SET `name` = 'nick'
+ LIMIT 1
+ })
+ end
+
+ adapter_is :sqlite3 do
+ sql.should be_like(%Q{
+ UPDATE "users"
+ SET "name" = 'nick'
+ LIMIT 1
+ })
+ end
+
+ adapter_is :postgresql do
+ sql.should be_like(%Q{
+ UPDATE "users"
+ SET "name" = E'nick'
+ LIMIT 1
+ })
+ end
+ end
+
+ describe 'when given values whose types correspond to the types of the attributes' do
+ before do
+ @update = Update.new(@relation, @relation[:name] => "nick")
+ end
+
+ it 'manufactures sql updating attributes' do
+ adapter_is :mysql do
+ @update.to_sql.should be_like(%Q{
+ UPDATE `users`
+ SET `name` = 'nick'
+ })
+ end
+
+ adapter_is :sqlite3 do
+ @update.to_sql.should be_like(%Q{
+ UPDATE "users"
+ SET "name" = 'nick'
+ })
+ end
+
+ adapter_is :postgresql do
+ @update.to_sql.should be_like(%Q{
+ UPDATE "users"
+ SET "name" = E'nick'
+ })
+ end
+ end
+ end
+
+ describe 'when given values whose types differ from from the types of the attributes' do
+ before do
+ @update = Update.new(@relation, @relation[:id] => '1-asdf')
+ end
+
+ it 'manufactures sql updating attributes' do
+ adapter_is :mysql do
+ @update.to_sql.should be_like(%Q{
+ UPDATE `users`
+ SET `id` = 1
+ })
+ end
+
+ adapter_is_not :mysql do
+ @update.to_sql.should be_like(%Q{
+ UPDATE "users"
+ SET "id" = 1
+ })
+ end
+ end
+ end
+
+ describe 'when the relation is a where' do
+ before do
+ @update = Update.new(
+ @relation.where(@relation[:id].eq(1)),
+ @relation[:name] => "nick"
+ )
+ end
+
+ it 'manufactures sql updating a where relation' do
+ adapter_is :mysql do
+ @update.to_sql.should be_like(%Q{
+ UPDATE `users`
+ SET `name` = 'nick'
+ WHERE `users`.`id` = 1
+ })
+ end
+
+ adapter_is :sqlite3 do
+ @update.to_sql.should be_like(%Q{
+ UPDATE "users"
+ SET "name" = 'nick'
+ WHERE "users"."id" = 1
+ })
+ end
+
+ adapter_is :postgresql do
+ @update.to_sql.should be_like(%Q{
+ UPDATE "users"
+ SET "name" = E'nick'
+ WHERE "users"."id" = 1
+ })
+ end
+ end
+ end
+ end
+
+ end
+end
diff --git a/spec/arel/engines/sql/unit/relations/where_spec.rb b/spec/arel/engines/sql/unit/relations/where_spec.rb
new file mode 100644
index 0000000000..4f0cce1e01
--- /dev/null
+++ b/spec/arel/engines/sql/unit/relations/where_spec.rb
@@ -0,0 +1,56 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
+
+module Arel
+ describe Where do
+ before do
+ @relation = Table.new(:users)
+ @predicate = @relation[:id].eq(1)
+ end
+
+ describe '#to_sql' do
+ describe 'when given a predicate' do
+ it "manufactures sql with where clause conditions" do
+ sql = Where.new(@relation, @predicate).to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ WHERE `users`.`id` = 1
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ WHERE "users"."id" = 1
+ })
+ end
+ end
+ end
+
+ describe 'when given a string' do
+ it "passes the string through to the where clause" do
+ sql = Where.new(@relation, 'asdf').to_sql
+
+ adapter_is :mysql do
+ sql.should be_like(%Q{
+ SELECT `users`.`id`, `users`.`name`
+ FROM `users`
+ WHERE asdf
+ })
+ end
+
+ adapter_is_not :mysql do
+ sql.should be_like(%Q{
+ SELECT "users"."id", "users"."name"
+ FROM "users"
+ WHERE asdf
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/arel/integration/joins/with_adjacency_spec.rb b/spec/arel/integration/joins/with_adjacency_spec.rb
deleted file mode 100644
index 559b5bbe1a..0000000000
--- a/spec/arel/integration/joins/with_adjacency_spec.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Join do
- before do
- @relation1 = Arel(:users)
- @relation2 = @relation1.alias
- @predicate = @relation1[:id].eq(@relation2[:id])
- end
-
- describe 'when joining a relation to itself' do
- describe '#to_sql' do
- it 'manufactures sql aliasing the table and attributes properly in the join predicate and the where clause' do
- @relation1.join(@relation2).on(@predicate).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
- FROM `users`
- INNER JOIN `users` AS `users_2`
- ON `users`.`id` = `users_2`.`id`
- ")
- end
-
- describe 'when joining with a where on the same relation' do
- it 'manufactures sql aliasing the tables properly' do
- @relation1 \
- .join(@relation2.where(@relation2[:id].eq(1))) \
- .on(@predicate) \
- .to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
- FROM `users`
- INNER JOIN `users` AS `users_2`
- ON `users`.`id` = `users_2`.`id` AND `users_2`.`id` = 1
- ")
- end
-
- describe 'when the where occurs before the alias' do
- it 'manufactures sql aliasing the predicates properly' do
- relation2 = @relation1.where(@relation1[:id].eq(1)).alias
- @relation1 \
- .join(relation2) \
- .on(relation2[:id].eq(@relation1[:id])) \
- .to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`
- FROM `users`
- INNER JOIN `users` AS `users_2`
- ON `users_2`.`id` = `users`.`id` AND `users_2`.`id` = 1
- ")
- end
- end
- end
-
- describe 'when joining the relation to itself multiple times' do
- before do
- @relation3 = @relation1.alias
- end
-
- describe 'when joining left-associatively' do
- it 'manufactures sql aliasing the tables properly' do
- @relation1 \
- .join(@relation2 \
- .join(@relation3) \
- .on(@relation2[:id].eq(@relation3[:id]))) \
- .on(@relation1[:id].eq(@relation2[:id])) \
- .to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
- FROM `users`
- INNER JOIN `users` AS `users_2`
- ON `users`.`id` = `users_2`.`id`
- INNER JOIN `users` AS `users_3`
- ON `users_2`.`id` = `users_3`.`id`
- ")
- end
- end
-
- describe 'when joining right-associatively' do
- it 'manufactures sql aliasing the tables properly' do
- @relation1 \
- .join(@relation2).on(@relation1[:id].eq(@relation2[:id])) \
- .join(@relation3).on(@relation2[:id].eq(@relation3[:id])) \
- .to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `users_2`.`id`, `users_2`.`name`, `users_3`.`id`, `users_3`.`name`
- FROM `users`
- INNER JOIN `users` AS `users_2`
- ON `users`.`id` = `users_2`.`id`
- INNER JOIN `users` AS `users_3`
- ON `users_2`.`id` = `users_3`.`id`
- ")
- end
- end
- end
- end
-
- describe '[]' do
- describe 'when given an attribute belonging to both sub-relations' do
- it 'disambiguates the relation that serves as the ancestor to the attribute' do
- @relation1 \
- .join(@relation2) \
- .on(@predicate) \
- .should disambiguate_attributes(@relation1[:id], @relation2[:id])
- end
-
- describe 'when both relations are compound and only one is an alias' do
- it 'disambiguates the relation that serves as the ancestor to the attribute' do
- compound1 = @relation1.where(@predicate)
- compound2 = compound1.alias
- compound1 \
- .join(compound2) \
- .on(@predicate) \
- .should disambiguate_attributes(compound1[:id], compound2[:id])
- end
- end
-
- describe 'when the left relation is extremely compound' do
- it 'disambiguates the relation that serves as the ancestor to the attribute' do
- @relation1 \
- .where(@predicate) \
- .where(@predicate) \
- .join(@relation2) \
- .on(@predicate) \
- .should disambiguate_attributes(@relation1[:id], @relation2[:id])
- end
- end
-
- describe 'when the right relation is extremely compound' do
- it 'disambiguates the relation that serves as the ancestor to the attribute' do
- @relation1 \
- .join( \
- @relation2 \
- .where(@predicate) \
- .where(@predicate) \
- .where(@predicate)) \
- .on(@predicate) \
- .should disambiguate_attributes(@relation1[:id], @relation2[:id])
- end
- end
- end
- end
- end
- end
-end
diff --git a/spec/arel/integration/joins/with_aggregations_spec.rb b/spec/arel/integration/joins/with_aggregations_spec.rb
deleted file mode 100644
index 2b21dcaa1e..0000000000
--- a/spec/arel/integration/joins/with_aggregations_spec.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Join do
- before do
- @relation1 = Arel(:users)
- @relation2 = Arel(:photos)
- @predicate = @relation1[:id].eq(@relation2[:user_id])
- end
-
- describe 'when joining aggregated relations' do
- before do
- @aggregation = @relation2 \
- .group(@relation2[:user_id]) \
- .project(@relation2[:user_id], @relation2[:id].count.as(:cnt)) \
- end
-
- describe '#to_sql' do
- # CLEANUP
- it '' do
- @relation1.join(@relation2.take(3)).on(@predicate).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `photos_external`.`id`, `photos_external`.`user_id`, `photos_external`.`camera_id`
- FROM `users`
- INNER JOIN (SELECT `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id` FROM `photos` LIMIT 3) AS `photos_external`
- ON `users`.`id` = `photos_external`.`user_id`
- ")
- end
-
- describe 'with the aggregation on the right' do
- it 'manufactures sql joining the left table to a derived table' do
- @relation1.join(@aggregation).on(@predicate).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `photos_external`.`user_id`, `photos_external`.`cnt`
- FROM `users`
- INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
- ON `users`.`id` = `photos_external`.`user_id`
- ")
- end
- end
-
- describe 'with the aggregation on the left' do
- it 'manufactures sql joining the right table to a derived table' do
- @aggregation.join(@relation1).on(@predicate).to_sql.should be_like("
- SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `users`.`id`, `users`.`name`
- FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
- INNER JOIN `users`
- ON `users`.`id` = `photos_external`.`user_id`
- ")
- end
- end
-
- describe 'with the aggregation on both sides' do
- it 'it properly aliases the aggregations' do
- aggregation2 = @aggregation.alias
- @aggregation.join(aggregation2).on(aggregation2[:user_id].eq(@aggregation[:user_id])).to_sql.should be_like("
- SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `photos_external_2`.`user_id`, `photos_external_2`.`cnt`
- FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external`
- INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photos_external_2`
- ON `photos_external_2`.`user_id` = `photos_external`.`user_id`
- ")
- end
- end
-
- describe 'when the aggration has a where' do
- describe 'with the aggregation on the left' do
- it "manufactures sql keeping wheres on the aggregation within the derived table" do
- @relation1.join(@aggregation.where(@aggregation[:user_id].eq(1))).on(@predicate).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `photos_external`.`user_id`, `photos_external`.`cnt`
- FROM `users`
- INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` WHERE `photos`.`user_id` = 1 GROUP BY `photos`.`user_id`) AS `photos_external`
- ON `users`.`id` = `photos_external`.`user_id`
- ")
- end
- end
-
- describe 'with the aggregation on the right' do
- it "manufactures sql keeping wheres on the aggregation within the derived table" do
- @aggregation.where(@aggregation[:user_id].eq(1)).join(@relation1).on(@predicate).to_sql.should be_like("
- SELECT `photos_external`.`user_id`, `photos_external`.`cnt`, `users`.`id`, `users`.`name`
- FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` WHERE `photos`.`user_id` = 1 GROUP BY `photos`.`user_id`) AS `photos_external`
- INNER JOIN `users`
- ON `users`.`id` = `photos_external`.`user_id`
- ")
- end
- end
- end
- end
- end
- end
-end
diff --git a/spec/arel/integration/joins/with_compounds_spec.rb b/spec/arel/integration/joins/with_compounds_spec.rb
deleted file mode 100644
index 95fadc23d6..0000000000
--- a/spec/arel/integration/joins/with_compounds_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Join do
- before do
- @relation1 = Arel(:users)
- @relation2 = Arel(:photos)
- @predicate = @relation1[:id].eq(@relation2[:user_id])
- end
-
- describe '#to_sql' do
- describe 'when the join contains a where' do
- describe 'and the where is given a string' do
- it 'does not escape the string' do
- @relation1 \
- .join(@relation2.where("asdf")) \
- .on(@predicate) \
- .to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
- FROM `users`
- INNER JOIN `photos`
- ON `users`.`id` = `photos`.`user_id` AND asdf
- ")
- end
- end
- end
-
- describe 'when a compound contains a join' do
- describe 'and the compound is a where' do
- it 'manufactures sql disambiguating the tables' do
- @relation1 \
- .where(@relation1[:id].eq(1)) \
- .join(@relation2) \
- .on(@predicate) \
- .where(@relation1[:id].eq(1)) \
- .to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
- FROM `users`
- INNER JOIN `photos`
- ON `users`.`id` = `photos`.`user_id`
- WHERE `users`.`id` = 1
- AND `users`.`id` = 1
- ")
- end
- end
-
- describe 'and the compound is a group' do
- it 'manufactures sql disambiguating the tables' do
- @relation1 \
- .join(@relation2) \
- .on(@predicate) \
- .group(@relation1[:id]) \
- .to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
- FROM `users`
- INNER JOIN `photos`
- ON `users`.`id` = `photos`.`user_id`
- GROUP BY `users`.`id`
- ")
- end
- end
- end
- end
- end
-end
diff --git a/spec/arel/unit/predicates/binary_spec.rb b/spec/arel/unit/predicates/binary_spec.rb
deleted file mode 100644
index 56fcf2d8ad..0000000000
--- a/spec/arel/unit/predicates/binary_spec.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Binary do
- before do
- @relation = Table.new(:users)
- @attribute1 = @relation[:id]
- @attribute2 = @relation[:name]
- class ConcreteBinary < Binary
- def predicate_sql
- "<=>"
- end
- end
- end
-
- describe "with compound predicates" do
- before do
- @operand1 = ConcreteBinary.new(@attribute1, 1)
- @operand2 = ConcreteBinary.new(@attribute2, "name")
- end
-
- describe Or do
- describe "#to_sql" do
- it "manufactures sql with an OR operation" do
- Or.new(@operand1, @operand2).to_sql.should be_like("
- (`users`.`id` <=> 1 OR `users`.`name` <=> 'name')
- ")
- end
- end
- end
-
- describe And do
- describe "#to_sql" do
- it "manufactures sql with an AND operation" do
- And.new(@operand1, @operand2).to_sql.should be_like("
- (`users`.`id` <=> 1 AND `users`.`name` <=> 'name')
- ")
- end
- end
- end
- end
-
- describe '#to_sql' do
- describe 'when relating two attributes' do
- it 'manufactures sql with a binary operation' do
- ConcreteBinary.new(@attribute1, @attribute2).to_sql.should be_like("
- `users`.`id` <=> `users`.`name`
- ")
- end
- end
-
- describe 'when relating an attribute and a value' do
- before do
- @value = "1-asdf"
- end
-
- describe 'when relating to an integer attribute' do
- it 'formats values as integers' do
- ConcreteBinary.new(@attribute1, @value).to_sql.should be_like("
- `users`.`id` <=> 1
- ")
- end
- end
-
- describe 'when relating to a string attribute' do
- it 'formats values as strings' do
- ConcreteBinary.new(@attribute2, @value).to_sql.should be_like("
- `users`.`name` <=> '1-asdf'
- ")
- end
- end
- end
- end
-
- describe '#bind' do
- before do
- @another_relation = @relation.alias
- end
-
- describe 'when both operands are attributes' do
- it "manufactures an expression with the attributes bound to the relation" do
- ConcreteBinary.new(@attribute1, @attribute2).bind(@another_relation). \
- should == ConcreteBinary.new(@another_relation[@attribute1], @another_relation[@attribute2])
- end
- end
-
- describe 'when an operand is a value' do
- it "manufactures an expression with unmodified values" do
- ConcreteBinary.new(@attribute1, "asdf").bind(@another_relation). \
- should == ConcreteBinary.new(@attribute1.find_correlate_in(@another_relation), "asdf".find_correlate_in(@another_relation))
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/predicates/in_spec.rb b/spec/arel/unit/predicates/in_spec.rb
deleted file mode 100644
index 797798a77f..0000000000
--- a/spec/arel/unit/predicates/in_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe In do
- before do
- @relation = Table.new(:users)
- @attribute = @relation[:id]
- end
-
- describe '#to_sql' do
- describe 'when relating to an array' do
- describe 'when the array\'s elements are the same type as the attribute' do
- before do
- @array = [1, 2, 3]
- end
-
- it 'manufactures sql with a comma separated list' do
- In.new(@attribute, @array).to_sql.should be_like("
- `users`.`id` IN (1, 2, 3)
- ")
- end
- end
-
- describe 'when the array\'s elements are not same type as the attribute' do
- before do
- @array = ['1-asdf', 2, 3]
- end
-
- it 'formats values in the array as the type of the attribute' do
- In.new(@attribute, @array).to_sql.should be_like("
- `users`.`id` IN (1, 2, 3)
- ")
- end
- end
- end
-
- describe 'when relating to a range' do
- before do
- @range = 1..2
- end
-
- it 'manufactures sql with a between' do
- In.new(@attribute, @range).to_sql.should be_like("
- `users`.`id` BETWEEN 1 AND 2
- ")
- end
- end
-
- describe 'when relating to a relation' do
- it 'manufactures sql with a subselect' do
- In.new(@attribute, @relation).to_sql.should be_like("
- `users`.`id` IN (SELECT `users`.`id`, `users`.`name` FROM `users`)
- ")
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/predicates/predicates_spec.rb b/spec/arel/unit/predicates/predicates_spec.rb
deleted file mode 100644
index d11637cabe..0000000000
--- a/spec/arel/unit/predicates/predicates_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Predicate do
- before do
- @relation = Table.new(:users)
- @attribute1 = @relation[:id]
- @attribute2 = @relation[:name]
- @operand1 = Equality.new(@attribute1, 1)
- @operand2 = Equality.new(@attribute2, "name")
- end
-
- describe "when being combined with another predicate with AND logic" do
- describe "#to_sql" do
- it "manufactures sql with an AND operation" do
- @operand1.and(@operand2).to_sql.should be_like("
- (`users`.`id` = 1 AND `users`.`name` = 'name')
- ")
- end
- end
- end
-
- describe "when being combined with another predicate with OR logic" do
- describe "#to_sql" do
- it "manufactures sql with an OR operation" do
- @operand1.or(@operand2).to_sql.should be_like("
- (`users`.`id` = 1 OR `users`.`name` = 'name')
- ")
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/relations/alias_spec.rb b/spec/arel/unit/relations/alias_spec.rb
deleted file mode 100644
index 460a0ed0df..0000000000
--- a/spec/arel/unit/relations/alias_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Alias do
- before do
- @relation = Table.new(:users)
- end
-
- describe '==' do
- it "obtains if the objects are the same" do
- Alias.new(@relation).should_not == Alias.new(@relation)
- (aliaz = Alias.new(@relation)).should == aliaz
- end
- end
-
- describe '#to_sql' do
- describe 'when there is no ambiguity' do
- it 'does not alias table names anywhere a table name can appear' do
- @relation \
- .where(@relation[:id].eq(1)) \
- .order(@relation[:id]) \
- .project(@relation[:id]) \
- .group(@relation[:id]) \
- .alias \
- .to_sql.should be_like("
- SELECT `users`.`id`
- FROM `users`
- WHERE `users`.`id` = 1
- GROUP BY `users`.`id`
- ORDER BY `users`.`id`
- ")
- end
- end
- end
- end
-end
diff --git a/spec/arel/unit/relations/delete_spec.rb b/spec/arel/unit/relations/delete_spec.rb
deleted file mode 100644
index fa887d20fd..0000000000
--- a/spec/arel/unit/relations/delete_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Deletion do
- before do
- @relation = Table.new(:users)
- end
-
- describe '#to_sql' do
- it 'manufactures sql deleting a table relation' do
- Deletion.new(@relation).to_sql.should be_like("
- DELETE
- FROM `users`
- ")
- end
-
- it 'manufactures sql deleting a where relation' do
- Deletion.new(@relation.where(@relation[:id].eq(1))).to_sql.should be_like("
- DELETE
- FROM `users`
- WHERE `users`.`id` = 1
- ")
- end
-
- it "manufactures sql deleting a ranged relation" do
- Deletion.new(@relation.take(1)).to_sql.should be_like("
- DELETE
- FROM `users`
- LIMIT 1
- ")
- end
- end
-
- describe '#call' do
- it 'executes a delete on the connection' do
- deletion = Deletion.new(@relation)
- mock(connection = Object.new).delete(deletion.to_sql)
- deletion.call(connection)
- end
- end
- end
-end
diff --git a/spec/arel/unit/relations/group_spec.rb b/spec/arel/unit/relations/group_spec.rb
deleted file mode 100644
index a0147b9416..0000000000
--- a/spec/arel/unit/relations/group_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Group do
- before do
- @relation = Table.new(:users)
- @attribute = @relation[:id]
- end
-
- describe '#to_sql' do
- describe 'when given a predicate' do
- it "manufactures sql with where clause conditions" do
- Group.new(@relation, @attribute).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- GROUP BY `users`.`id`
- ")
- end
- end
-
- describe 'when given a string' do
- it "passes the string through to the where clause" do
- Group.new(@relation, 'asdf').to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- GROUP BY asdf
- ")
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/relations/insert_spec.rb b/spec/arel/unit/relations/insert_spec.rb
deleted file mode 100644
index 441c97b290..0000000000
--- a/spec/arel/unit/relations/insert_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Insert do
- before do
- @relation = Table.new(:users)
- end
-
- describe '#to_sql' do
- it 'manufactures sql inserting data when given multiple rows' do
- pending 'it should insert multiple rows'
- @insertion = Insert.new(@relation, [@relation[:name] => "nick", @relation[:name] => "bryan"])
-
- @insertion.to_sql.should be_like("
- INSERT
- INTO `users`
- (`name`) VALUES ('nick'), ('bryan')
- ")
- end
-
- it 'manufactures sql inserting data when given multiple values' do
- @insertion = Insert.new(@relation, @relation[:id] => "1", @relation[:name] => "nick")
-
- @insertion.to_sql.should be_like("
- INSERT
- INTO `users`
- (`id`, `name`) VALUES (1, 'nick')
- ")
- end
-
- describe 'when given values whose types correspond to the types of the attributes' do
- before do
- @insertion = Insert.new(@relation, @relation[:name] => "nick")
- end
-
- it 'manufactures sql inserting data' do
- @insertion.to_sql.should be_like("
- INSERT
- INTO `users`
- (`name`) VALUES ('nick')
- ")
- end
- end
-
- describe 'when given values whose types differ from from the types of the attributes' do
- before do
- @insertion = Insert.new(@relation, @relation[:id] => '1-asdf')
- end
-
- it 'manufactures sql inserting data' do
- @insertion.to_sql.should be_like("
- INSERT
- INTO `users`
- (`id`) VALUES (1)
- ")
- end
- end
- end
-
- describe '#call' do
- before do
- @insertion = Insert.new(@relation, @relation[:name] => "nick")
- end
-
- it 'executes an insert on the connection' do
- mock(connection = Object.new).insert(@insertion.to_sql)
- @insertion.call(connection)
- end
- end
- end
-end
diff --git a/spec/arel/unit/relations/join_spec.rb b/spec/arel/unit/relations/join_spec.rb
deleted file mode 100644
index 1698bf9647..0000000000
--- a/spec/arel/unit/relations/join_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Join do
- before do
- @relation1 = Table.new(:users)
- @relation2 = Table.new(:photos)
- @predicate = @relation1[:id].eq(@relation2[:user_id])
- end
-
- describe 'hashing' do
- it 'implements hash equality' do
- Join.new("INNER JOIN", @relation1, @relation2, @predicate) \
- .should hash_the_same_as(Join.new("INNER JOIN", @relation1, @relation2, @predicate))
- end
- end
-
- describe '#engine' do
- it "delegates to a relation's engine" do
- Join.new("INNER JOIN", @relation1, @relation2, @predicate).engine.should == @relation1.engine
- end
- end
-
- describe '#attributes' do
- it 'combines the attributes of the two relations' do
- join = Join.new("INNER JOIN", @relation1, @relation2, @predicate)
- join.attributes.should ==
- (@relation1.attributes + @relation2.attributes).collect { |a| a.bind(join) }
- end
- end
-
- describe '#to_sql' do
- describe 'when joining with another relation' do
- it 'manufactures sql joining the two tables on the predicate' do
- Join.new("INNER JOIN", @relation1, @relation2, @predicate).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
- FROM `users`
- INNER JOIN `photos` ON `users`.`id` = `photos`.`user_id`
- ")
- end
- end
-
- describe 'when joining with a string' do
- it "passes the string through to the where clause" do
- Join.new("INNER JOIN asdf ON fdsa", @relation1).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- INNER JOIN asdf ON fdsa
- ")
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/relations/order_spec.rb b/spec/arel/unit/relations/order_spec.rb
deleted file mode 100644
index d373a8ba12..0000000000
--- a/spec/arel/unit/relations/order_spec.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Order do
- before do
- @relation = Table.new(:users)
- @attribute = @relation[:id]
- end
-
- describe '#to_sql' do
- describe "when given an attribute" do
- it "manufactures sql with an order clause populated by the attribute" do
- Order.new(@relation, @attribute).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- ORDER BY `users`.`id`
- ")
- end
- end
-
- describe "when given multiple attributes" do
- before do
- @another_attribute = @relation[:name]
- end
-
- it "manufactures sql with an order clause populated by comma-separated attributes" do
- Order.new(@relation, @attribute, @another_attribute).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- ORDER BY `users`.`id`, `users`.`name`
- ")
- end
- end
-
- describe "when given a string" do
- before do
- @string = "asdf"
- end
-
- it "passes the string through to the order clause" do
- Order.new(@relation, @string).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- ORDER BY asdf
- ")
- end
- end
-
- describe "when ordering an ordered relation" do
- before do
- @ordered_relation = Order.new(@relation, @attribute)
- @another_attribute = @relation[:name]
- end
-
- it "manufactures sql with the order clause of the last ordering preceding the first ordering" do
- Order.new(@ordered_relation, @another_attribute).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- ORDER BY `users`.`name`, `users`.`id`
- ")
- end
- end
- end
- end
-end
- \ No newline at end of file
diff --git a/spec/arel/unit/relations/project_spec.rb b/spec/arel/unit/relations/project_spec.rb
deleted file mode 100644
index f389b18c54..0000000000
--- a/spec/arel/unit/relations/project_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Project do
- before do
- @relation = Table.new(:users)
- @attribute = @relation[:id]
- end
-
- describe '#attributes' do
- before do
- @projection = Project.new(@relation, @attribute)
- end
-
- it "manufactures attributes associated with the projection relation" do
- @projection.attributes.should == [@attribute].collect { |a| a.bind(@projection) }
- end
- end
-
- describe '#to_sql' do
- describe 'when given an attribute' do
- it "manufactures sql with a limited select clause" do
- Project.new(@relation, @attribute).to_sql.should be_like("
- SELECT `users`.`id`
- FROM `users`
- ")
- end
- end
-
- describe 'when given a relation' do
- before do
- @scalar_relation = Project.new(@relation, @relation[:name])
- end
-
- it "manufactures sql with scalar selects" do
- Project.new(@relation, @scalar_relation).to_sql.should be_like("
- SELECT (SELECT `users`.`name` FROM `users`) AS `users` FROM `users`
- ")
- end
- end
-
- describe 'when given a string' do
- it "passes the string through to the select clause" do
- Project.new(@relation, 'asdf').to_sql.should be_like("
- SELECT asdf FROM `users`
- ")
- end
- end
-
- describe 'when given an expression' do
- it 'manufactures sql with expressions' do
- @relation.project(@attribute.count).to_sql.should be_like("
- SELECT COUNT(`users`.`id`) AS count_id
- FROM `users`
- ")
- end
-
- it 'manufactures sql with distinct expressions' do
- @relation.project(@attribute.count(true)).to_sql.should be_like("
- SELECT COUNT(DISTINCT `users`.`id`) AS count_id
- FROM `users`
- ")
- end
- end
- end
-
- describe '#externalizable?' do
- describe 'when the projections are attributes' do
- it 'returns false' do
- Project.new(@relation, @attribute).should_not be_externalizable
- end
- end
-
- describe 'when the projections include an aggregation' do
- it "obtains" do
- Project.new(@relation, @attribute.sum).should be_externalizable
- end
- end
- end
- end
-end
diff --git a/spec/arel/unit/relations/skip_spec.rb b/spec/arel/unit/relations/skip_spec.rb
deleted file mode 100644
index d83c969aa8..0000000000
--- a/spec/arel/unit/relations/skip_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Skip do
- before do
- @relation = Table.new(:users)
- @skipped = 4
- end
-
- describe '#to_sql' do
- it "manufactures sql with limit and offset" do
- Skip.new(@relation, @skipped).to_s.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- OFFSET #{@skipped}
- ")
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/relations/table_spec.rb b/spec/arel/unit/relations/table_spec.rb
deleted file mode 100644
index 54520bf3b6..0000000000
--- a/spec/arel/unit/relations/table_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Table do
- before do
- @relation = Table.new(:users)
- end
-
- describe '[]' do
- describe 'when given a', Symbol do
- it "manufactures an attribute if the symbol names an attribute within the relation" do
- @relation[:id].should == Attribute.new(@relation, :id)
- @relation[:does_not_exist].should be_nil
- end
- end
-
- describe 'when given an', Attribute do
- it "returns the attribute if the attribute is within the relation" do
- @relation[@relation[:id]].should == @relation[:id]
- end
-
- it "returns nil if the attribtue is not within the relation" do
- another_relation = Table.new(:photos)
- @relation[another_relation[:id]].should be_nil
- end
- end
-
- describe 'when given an', Expression do
- before do
- @expression = @relation[:id].count
- end
-
- it "returns the Expression if the Expression is within the relation" do
- @relation[@expression].should be_nil
- end
- end
- end
-
- describe '#to_sql' do
- it "manufactures a simple select query" do
- @relation.to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- ")
- end
- end
-
- describe '#column_for' do
- it "returns the column corresponding to the attribute" do
- @relation.column_for(@relation[:id]).should == @relation.columns.detect { |c| c.name == 'id' }
- end
- end
-
- describe '#attributes' do
- it 'manufactures attributes corresponding to columns in the table' do
- @relation.attributes.should == [
- Attribute.new(@relation, :id),
- Attribute.new(@relation, :name)
- ]
- end
-
- describe '#reset' do
- it "reloads columns from the database" do
- lambda { stub(@relation.engine).columns { [] } }.should_not change { @relation.attributes }
- lambda { @relation.reset }.should change { @relation.attributes }
- end
- end
- end
-
- describe 'hashing' do
- it "implements hash equality" do
- Table.new(:users).should hash_the_same_as(Table.new(:users))
- Table.new(:users).should_not hash_the_same_as(Table.new(:photos))
- end
- end
-
- describe '#engine' do
- it "defaults to global engine" do
- Table.engine = engine = Engine.new
- Table.new(:users).engine.should == engine
- end
-
- it "can be specified" do
- Table.new(:users, engine = Engine.new).engine.should == engine
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/relations/take_spec.rb b/spec/arel/unit/relations/take_spec.rb
deleted file mode 100644
index dca7806057..0000000000
--- a/spec/arel/unit/relations/take_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Take do
- before do
- @relation = Table.new(:users)
- @taken = 4
- end
-
- describe '#to_sql' do
- it "manufactures sql with limit and offset" do
- Take.new(@relation, @taken).to_s.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- LIMIT #{@taken}
- ")
- end
- end
- end
-end \ No newline at end of file
diff --git a/spec/arel/unit/relations/update_spec.rb b/spec/arel/unit/relations/update_spec.rb
deleted file mode 100644
index b67369251f..0000000000
--- a/spec/arel/unit/relations/update_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Update do
- before do
- @relation = Table.new(:users)
- end
-
- describe '#to_sql' do
- it "manufactures sql updating attributes when given multiple attributes" do
- Update.new(@relation, @relation[:id] => 1, @relation[:name] => "nick").to_sql.should be_like("
- UPDATE `users`
- SET `id` = 1, `name` = 'nick'
- ")
- end
-
- it "manufactures sql updating attributes when given a ranged relation" do
- Update.new(@relation.take(1), @relation[:name] => "nick").to_sql.should be_like("
- UPDATE `users`
- SET `name` = 'nick'
- LIMIT 1
- ")
- end
-
- describe 'when given values whose types correspond to the types of the attributes' do
- before do
- @update = Update.new(@relation, @relation[:name] => "nick")
- end
-
- it 'manufactures sql updating attributes' do
- @update.to_sql.should be_like("
- UPDATE `users`
- SET `name` = 'nick'
- ")
- end
- end
-
- describe 'when given values whose types differ from from the types of the attributes' do
- before do
- @update = Update.new(@relation, @relation[:id] => '1-asdf')
- end
-
- it 'manufactures sql updating attributes' do
- @update.to_sql.should be_like("
- UPDATE `users`
- SET `id` = 1
- ")
- end
- end
-
- describe 'when the relation is a where' do
- before do
- @update = Update.new(
- @relation.where(@relation[:id].eq(1)),
- @relation[:name] => "nick"
- )
- end
-
- it 'manufactures sql updating a where relation' do
- @update.to_sql.should be_like("
- UPDATE `users`
- SET `name` = 'nick'
- WHERE `users`.`id` = 1
- ")
- end
- end
- end
-
- describe '#call' do
- before do
- @update = Update.new(@relation, @relation[:name] => "nick")
- end
-
- it 'executes an update on the connection' do
- mock(connection = Object.new).update(@update.to_sql)
- @update.call(connection)
- end
- end
-
- end
-end
diff --git a/spec/arel/unit/relations/where_spec.rb b/spec/arel/unit/relations/where_spec.rb
deleted file mode 100644
index 8ef4d54b63..0000000000
--- a/spec/arel/unit/relations/where_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
-
-module Arel
- describe Where do
- before do
- @relation = Table.new(:users)
- @predicate = @relation[:id].eq(1)
- end
-
- describe '#initialize' do
- it "manufactures nested where relations if multiple predicates are provided" do
- another_predicate = @relation[:name].lt(2)
- Where.new(@relation, @predicate, another_predicate). \
- should == Where.new(Where.new(@relation, another_predicate), @predicate)
- end
- end
-
- describe '#to_sql' do
- describe 'when given a predicate' do
- it "manufactures sql with where clause conditions" do
- Where.new(@relation, @predicate).to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- WHERE `users`.`id` = 1
- ")
- end
- end
-
- describe 'when given a string' do
- it "passes the string through to the where clause" do
- Where.new(@relation, 'asdf').to_sql.should be_like("
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- WHERE asdf
- ")
- end
- end
- end
- end
-end
diff --git a/spec/connections/mysql_connection.rb b/spec/connections/mysql_connection.rb
new file mode 100644
index 0000000000..a58ddc35ef
--- /dev/null
+++ b/spec/connections/mysql_connection.rb
@@ -0,0 +1,15 @@
+require "activerecord"
+puts "Using native MySQL"
+
+ActiveRecord::Base.logger = Logger.new("debug.log")
+
+ActiveRecord::Base.configurations = {
+ 'unit' => {
+ :adapter => 'mysql',
+ :username => 'rails',
+ :encoding => 'utf8',
+ :database => 'arel_unit',
+ }
+}
+
+ActiveRecord::Base.establish_connection 'unit'
diff --git a/spec/connections/postgresql_connection.rb b/spec/connections/postgresql_connection.rb
new file mode 100644
index 0000000000..e376d33ec6
--- /dev/null
+++ b/spec/connections/postgresql_connection.rb
@@ -0,0 +1,14 @@
+require "activerecord"
+puts "Using native PostgreSQL"
+
+ActiveRecord::Base.logger = Logger.new("debug.log")
+
+ActiveRecord::Base.configurations = {
+ 'unit' => {
+ :adapter => 'postgresql',
+ :encoding => 'utf8',
+ :database => 'arel_unit',
+ }
+}
+
+ActiveRecord::Base.establish_connection 'unit'
diff --git a/spec/connections/sqlite3_connection.rb b/spec/connections/sqlite3_connection.rb
new file mode 100644
index 0000000000..9e9503e0ca
--- /dev/null
+++ b/spec/connections/sqlite3_connection.rb
@@ -0,0 +1,25 @@
+require "rubygems"
+require "activerecord"
+puts "Using native SQLite3"
+
+ActiveRecord::Base.logger = Logger.new("debug.log")
+
+db_file = "spec/fixtures/fixture_database.sqlite3"
+
+ActiveRecord::Base.configurations = {
+ "unit" => {
+ :adapter => 'sqlite3',
+ :database => db_file,
+ :timeout => 5000
+ }
+}
+
+unless File.exist?(db_file)
+ puts "SQLite3 database not found at #{db_file}. Rebuilding it."
+ FileUtils.mkdir_p(File.dirname(db_file))
+ sqlite_command = %Q{sqlite3 "#{db_file}" "create table a (a integer); drop table a;"}
+ puts "Executing '#{sqlite_command}'"
+ raise "Seems that there is no sqlite3 executable available" unless system(sqlite_command)
+end
+
+ActiveRecord::Base.establish_connection("unit")
diff --git a/spec/doubles/database.rb b/spec/doubles/database.rb
deleted file mode 100644
index f8a4b38e17..0000000000
--- a/spec/doubles/database.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-module Fake
- class Engine
- def connection
- @conn ||= Connection.new
- end
- end
-
- class Connection
- include ActiveRecord::ConnectionAdapters::Quoting
-
- def columns(table_name, comment)
- { "users" =>
- [
- Column.new("id", :integer),
- Column.new("name", :string)
- ],
- "photos" =>
- [
- Column.new("id", :integer),
- Column.new("user_id", :integer),
- Column.new("camera_id", :integer)
- ]
- }[table_name]
- end
-
- def execute(*args)
- []
- end
-
- def quote_column_name(column_name)
- "`#{column_name}`"
- end
-
- def quote_table_name(table_name)
- "`#{table_name}`"
- end
-
- def supports_count_distinct?
- true
- end
- end
-
- class Column
- attr_reader :name, :type
-
- def initialize(name, type)
- @name = name
- @type = type
- end
- end
-end
diff --git a/spec/doubles/hash.rb b/spec/doubles/hash.rb
index 97d25742cb..32c5b98058 100644
--- a/spec/doubles/hash.rb
+++ b/spec/doubles/hash.rb
@@ -2,19 +2,19 @@ class Hash
def ordered_array
to_a.sort { |(key1, value1), (key2, value2)| key1.hash <=> key2.hash }
end
-
+
def keys
ordered_array.collect(&:first)
end
-
+
def values
ordered_array.collect { |_, v| v }
end
-
+
def each(&block)
ordered_array.each(&block)
end
-
+
def shift
returning to_a.first do |k, v|
delete(k)
diff --git a/spec/matchers/be_like.rb b/spec/matchers/be_like.rb
index 4ff5bc532f..c9d4d4b979 100644
--- a/spec/matchers/be_like.rb
+++ b/spec/matchers/be_like.rb
@@ -3,22 +3,22 @@ module BeLikeMatcher
def initialize(expected)
@expected = expected
end
-
+
def matches?(actual)
@actual = actual
@expected.gsub(/\s+/, ' ').strip == @actual.gsub(/\s+/, ' ').strip
end
-
+
def failure_message
"expected\n#{@actual}\nto be like\n#{@expected}"
end
-
+
def negative_failure_message
"expected\n#{@actual}\nto be unlike\n#{@expected}"
end
end
-
+
def be_like(expected)
BeLike.new(expected)
end
-end \ No newline at end of file
+end
diff --git a/spec/matchers/disambiguate_attributes.rb b/spec/matchers/disambiguate_attributes.rb
index bee7d22b0c..bc4a5215d4 100644
--- a/spec/matchers/disambiguate_attributes.rb
+++ b/spec/matchers/disambiguate_attributes.rb
@@ -3,7 +3,7 @@ module DisambiguateAttributesMatcher
def initialize(attributes)
@attributes = attributes
end
-
+
def matches?(actual)
@actual = actual
attribute1, attribute2 = @attributes
@@ -11,18 +11,18 @@ module DisambiguateAttributesMatcher
!@actual[attribute1].descends_from?(attribute2) &&
@actual[attribute2].descends_from?(attribute2)
end
-
+
def failure_message
""
# "expected #{@actual} to disambiguate its attributes"
end
-
+
def negative_failure_message
"expected #{@actual} to not disambiguate its attributes"
end
end
-
+
def disambiguate_attributes(*attributes)
DisambiguateAttributes.new(attributes)
end
-end \ No newline at end of file
+end
diff --git a/spec/matchers/hash_the_same_as.rb b/spec/matchers/hash_the_same_as.rb
index c1903b62b4..03e955a0cb 100644
--- a/spec/matchers/hash_the_same_as.rb
+++ b/spec/matchers/hash_the_same_as.rb
@@ -3,24 +3,24 @@ module HashTheSameAsMatcher
def initialize(expected)
@expected = expected
end
-
+
def matches?(actual)
@actual = actual
hash = {}
hash[@expected] = :some_arbitrary_value
hash[@actual] == :some_arbitrary_value
end
-
+
def failure_message
"expected #{@actual} to hash the same as #{@expected}; they must be `eql?` and have the same `#hash` value"
end
-
+
def negative_failure_message
"expected #{@actual} to hash differently than #{@expected}; they must not be `eql?` or have a differing `#hash` values"
end
end
-
+
def hash_the_same_as(expected)
HashTheSameAs.new(expected)
end
-end \ No newline at end of file
+end
diff --git a/spec/schemas/mysql_schema.rb b/spec/schemas/mysql_schema.rb
new file mode 100644
index 0000000000..dc2558fd6a
--- /dev/null
+++ b/spec/schemas/mysql_schema.rb
@@ -0,0 +1,18 @@
+sql = <<-SQL
+ DROP TABLE IF EXISTS users;
+ CREATE TABLE users (
+ id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ name VARCHAR(255) NOT NULL
+ );
+
+ DROP TABLE IF EXISTS photos;
+ CREATE TABLE photos (
+ id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ user_id INTEGER NOT NULL,
+ camera_id INTEGER NOT NULL
+ );
+SQL
+
+sql.split(/;/).select(&:present?).each do |sql_statement|
+ ActiveRecord::Base.connection.execute sql_statement
+end
diff --git a/spec/schemas/postgresql_schema.rb b/spec/schemas/postgresql_schema.rb
new file mode 100644
index 0000000000..30fa665902
--- /dev/null
+++ b/spec/schemas/postgresql_schema.rb
@@ -0,0 +1,18 @@
+sql = <<-SQL
+ DROP TABLE IF EXISTS users;
+ CREATE TABLE users (
+ id SERIAL PRIMARY KEY NOT NULL,
+ name VARCHAR(255) NOT NULL
+ );
+
+ DROP TABLE IF EXISTS photos;
+ CREATE TABLE photos (
+ id SERIAL PRIMARY KEY NOT NULL,
+ user_id INTEGER NOT NULL,
+ camera_id INTEGER NOT NULL
+ );
+SQL
+
+sql.split(/;/).select(&:present?).each do |sql_statement|
+ ActiveRecord::Base.connection.execute sql_statement
+end
diff --git a/spec/schemas/sqlite3_schema.rb b/spec/schemas/sqlite3_schema.rb
new file mode 100644
index 0000000000..94d224520e
--- /dev/null
+++ b/spec/schemas/sqlite3_schema.rb
@@ -0,0 +1,18 @@
+sql = <<-SQL
+ DROP TABLE IF EXISTS users;
+ CREATE TABLE users (
+ id INTEGER NOT NULL PRIMARY KEY,
+ name VARCHAR(255) NOT NULL
+ );
+
+ DROP TABLE IF EXISTS photos;
+ CREATE TABLE photos (
+ id INTEGER NOT NULL PRIMARY KEY,
+ user_id INTEGER NOT NULL,
+ camera_id INTEGER NOT NULL
+ );
+SQL
+
+sql.split(/;/).select(&:present?).each do |sql_statement|
+ ActiveRecord::Base.connection.execute sql_statement
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index ce539b6ffa..beb634fbd3 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -11,10 +11,37 @@ require 'arel'
Dir["#{dir}/#{helper}/*"].each { |m| require "#{dir}/#{helper}/#{File.basename(m)}" }
end
+module AdapterGuards
+ def adapter_is(name)
+ verify_adapter_name(name)
+ yield if name.to_s == adapter_name
+ end
+
+ def adapter_is_not(name)
+ verify_adapter_name(name)
+ yield if name.to_s != adapter_name
+ end
+
+ def adapter_name
+ name = ActiveRecord::Base.configurations["unit"][:adapter]
+ verify_adapter_name(name)
+ name
+ end
+
+ def verify_adapter_name(name)
+ raise "Invalid adapter name: #{name}" unless valid_adapters.include?(name.to_s)
+ end
+
+ def valid_adapters
+ %w[mysql postgresql sqlite3]
+ end
+end
+
Spec::Runner.configure do |config|
- config.include(BeLikeMatcher, HashTheSameAsMatcher, DisambiguateAttributesMatcher)
+ config.include BeLikeMatcher, HashTheSameAsMatcher, DisambiguateAttributesMatcher
+ config.include AdapterGuards
config.mock_with :rr
config.before do
- Arel::Table.engine = Arel::Engine.new(Fake::Engine.new)
+ Arel::Table.engine = Arel::Sql::Engine.new(ActiveRecord::Base)
end
end