diff options
author | Emilio Tagua <miloops@gmail.com> | 2009-05-26 12:41:52 -0300 |
---|---|---|
committer | Emilio Tagua <miloops@gmail.com> | 2009-05-26 12:41:52 -0300 |
commit | c9bbea6115be520dbd47bd30108c5622289deb26 (patch) | |
tree | ec418e01954c1bd2dcfebc7fbc8220fb04b50baf /spec/arel/engines/sql/unit | |
parent | ae1e0ac5e98a7e5a2894d0a431f8c34af6575cae (diff) | |
parent | 86364591af807ed3fa4a7304f53e6f3458cb4961 (diff) | |
download | rails-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/arel/engines/sql/unit')
21 files changed, 1356 insertions, 0 deletions
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/engines/sql/unit/primitives/value_spec.rb b/spec/arel/engines/sql/unit/primitives/value_spec.rb new file mode 100644 index 0000000000..ff3533f6ef --- /dev/null +++ b/spec/arel/engines/sql/unit/primitives/value_spec.rb @@ -0,0 +1,29 @@ +require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper') + +module Arel + describe Value do + before do + @relation = Table.new(:users) + end + + describe '#to_sql' do + it "appropriately quotes the value" do + Value.new(1, @relation).to_sql.should be_like('1') + + 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 + + describe '#format' do + it "returns the sql of the provided object" do + Value.new(1, @relation).format(@relation[:id]).should == @relation[:id].to_sql + 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 |