aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r--activerecord/test/cases/adapters/mysql2/annotate_test.rb37
-rw-r--r--activerecord/test/cases/adapters/postgresql/annotate_test.rb37
-rw-r--r--activerecord/test/cases/adapters/sqlite3/annotate_test.rb37
-rw-r--r--activerecord/test/cases/arel/delete_manager_test.rb18
-rw-r--r--activerecord/test/cases/arel/nodes/comment_test.rb22
-rw-r--r--activerecord/test/cases/arel/nodes/delete_statement_test.rb8
-rw-r--r--activerecord/test/cases/arel/nodes/insert_statement_test.rb8
-rw-r--r--activerecord/test/cases/arel/nodes/select_core_test.rb8
-rw-r--r--activerecord/test/cases/arel/nodes/update_statement_test.rb8
-rw-r--r--activerecord/test/cases/arel/select_manager_test.rb23
-rw-r--r--activerecord/test/cases/arel/support/fake_record.rb4
-rw-r--r--activerecord/test/cases/arel/update_manager_test.rb24
-rw-r--r--activerecord/test/cases/arel/visitors/depth_first_test.rb6
-rw-r--r--activerecord/test/cases/associations_test.rb99
-rw-r--r--activerecord/test/cases/relation/delete_all_test.rb19
-rw-r--r--activerecord/test/cases/relation/merging_test.rb12
-rw-r--r--activerecord/test/cases/relation/update_all_test.rb27
-rw-r--r--activerecord/test/cases/relation_test.rb52
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb10
-rw-r--r--activerecord/test/cases/scoping/relation_scoping_test.rb38
20 files changed, 497 insertions, 0 deletions
diff --git a/activerecord/test/cases/adapters/mysql2/annotate_test.rb b/activerecord/test/cases/adapters/mysql2/annotate_test.rb
new file mode 100644
index 0000000000..b512540073
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/annotate_test.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "models/post"
+
+class Mysql2AnnotateTest < ActiveRecord::Mysql2TestCase
+ fixtures :posts
+
+ def test_annotate_wraps_content_in_an_inline_comment
+ assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/}) do
+ posts = Post.select(:id).annotate("foo")
+ assert posts.first
+ end
+ end
+
+ def test_annotate_is_sanitized
+ assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/}) do
+ posts = Post.select(:id).annotate("*/foo/*")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/}) do
+ posts = Post.select(:id).annotate("**//foo//**")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* foo \*/ /\* bar \*/}) do
+ posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT `posts`\.`id` FROM `posts` /\* \+ MAX_EXECUTION_TIME\(1\) \*/}) do
+ posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)")
+ assert posts.first
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/annotate_test.rb b/activerecord/test/cases/adapters/postgresql/annotate_test.rb
new file mode 100644
index 0000000000..42a2861511
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/annotate_test.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "models/post"
+
+class PostgresqlAnnotateTest < ActiveRecord::PostgreSQLTestCase
+ fixtures :posts
+
+ def test_annotate_wraps_content_in_an_inline_comment
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/}) do
+ posts = Post.select(:id).annotate("foo")
+ assert posts.first
+ end
+ end
+
+ def test_annotate_is_sanitized
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/}) do
+ posts = Post.select(:id).annotate("*/foo/*")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/}) do
+ posts = Post.select(:id).annotate("**//foo//**")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/ /\* bar \*/}) do
+ posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* \+ MAX_EXECUTION_TIME\(1\) \*/}) do
+ posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)")
+ assert posts.first
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/sqlite3/annotate_test.rb b/activerecord/test/cases/adapters/sqlite3/annotate_test.rb
new file mode 100644
index 0000000000..6567a5eca3
--- /dev/null
+++ b/activerecord/test/cases/adapters/sqlite3/annotate_test.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "models/post"
+
+class SQLite3AnnotateTest < ActiveRecord::SQLite3TestCase
+ fixtures :posts
+
+ def test_annotate_wraps_content_in_an_inline_comment
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/}) do
+ posts = Post.select(:id).annotate("foo")
+ assert posts.first
+ end
+ end
+
+ def test_annotate_is_sanitized
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/}) do
+ posts = Post.select(:id).annotate("*/foo/*")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/}) do
+ posts = Post.select(:id).annotate("**//foo//**")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* foo \*/ /\* bar \*/}) do
+ posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
+ assert posts.first
+ end
+
+ assert_sql(%r{\ASELECT "posts"\."id" FROM "posts" /\* \+ MAX_EXECUTION_TIME\(1\) \*/}) do
+ posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)")
+ assert posts.first
+ end
+ end
+end
diff --git a/activerecord/test/cases/arel/delete_manager_test.rb b/activerecord/test/cases/arel/delete_manager_test.rb
index 0bad02f4d2..63cd1bffe3 100644
--- a/activerecord/test/cases/arel/delete_manager_test.rb
+++ b/activerecord/test/cases/arel/delete_manager_test.rb
@@ -49,5 +49,23 @@ module Arel
dm.where(table[:id].eq(10)).must_equal dm
end
end
+
+ describe "comment" do
+ it "chains" do
+ manager = Arel::DeleteManager.new
+ manager.comment("deleting").must_equal manager
+ end
+
+ it "appends a comment to the generated query" do
+ table = Table.new(:users)
+ dm = Arel::DeleteManager.new
+ dm.from table
+ dm.comment("deletion")
+ assert_match(%r{DELETE FROM "users" /\* deletion \*/}, dm.to_sql)
+
+ dm.comment("deletion", "with", "comment")
+ assert_match(%r{DELETE FROM "users" /\* deletion \*/ /\* with \*/ /\* comment \*/}, dm.to_sql)
+ end
+ end
end
end
diff --git a/activerecord/test/cases/arel/nodes/comment_test.rb b/activerecord/test/cases/arel/nodes/comment_test.rb
new file mode 100644
index 0000000000..bf5eaf4c5a
--- /dev/null
+++ b/activerecord/test/cases/arel/nodes/comment_test.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require_relative "../helper"
+require "yaml"
+
+module Arel
+ module Nodes
+ class CommentTest < Arel::Spec
+ describe "equality" do
+ it "is equal with equal contents" do
+ array = [Comment.new(["foo"]), Comment.new(["foo"])]
+ assert_equal 1, array.uniq.size
+ end
+
+ it "is not equal with different contents" do
+ array = [Comment.new(["foo"]), Comment.new(["bar"])]
+ assert_equal 2, array.uniq.size
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/arel/nodes/delete_statement_test.rb b/activerecord/test/cases/arel/nodes/delete_statement_test.rb
index 3f078063a4..8ba268653d 100644
--- a/activerecord/test/cases/arel/nodes/delete_statement_test.rb
+++ b/activerecord/test/cases/arel/nodes/delete_statement_test.rb
@@ -18,8 +18,10 @@ describe Arel::Nodes::DeleteStatement do
it "is equal with equal ivars" do
statement1 = Arel::Nodes::DeleteStatement.new
statement1.wheres = %w[a b c]
+ statement1.comment = Arel::Nodes::Comment.new(["comment"])
statement2 = Arel::Nodes::DeleteStatement.new
statement2.wheres = %w[a b c]
+ statement2.comment = Arel::Nodes::Comment.new(["comment"])
array = [statement1, statement2]
assert_equal 1, array.uniq.size
end
@@ -27,8 +29,14 @@ describe Arel::Nodes::DeleteStatement do
it "is not equal with different ivars" do
statement1 = Arel::Nodes::DeleteStatement.new
statement1.wheres = %w[a b c]
+ statement1.comment = Arel::Nodes::Comment.new(["comment"])
statement2 = Arel::Nodes::DeleteStatement.new
statement2.wheres = %w[1 2 3]
+ statement2.comment = Arel::Nodes::Comment.new(["comment"])
+ array = [statement1, statement2]
+ assert_equal 2, array.uniq.size
+ statement2.wheres = %w[a b c]
+ statement2.comment = Arel::Nodes::Comment.new(["other"])
array = [statement1, statement2]
assert_equal 2, array.uniq.size
end
diff --git a/activerecord/test/cases/arel/nodes/insert_statement_test.rb b/activerecord/test/cases/arel/nodes/insert_statement_test.rb
index 252a0d0d0b..036576b231 100644
--- a/activerecord/test/cases/arel/nodes/insert_statement_test.rb
+++ b/activerecord/test/cases/arel/nodes/insert_statement_test.rb
@@ -23,9 +23,11 @@ describe Arel::Nodes::InsertStatement do
statement1 = Arel::Nodes::InsertStatement.new
statement1.columns = %w[a b c]
statement1.values = %w[x y z]
+ statement1.comment = Arel::Nodes::Comment.new(["comment"])
statement2 = Arel::Nodes::InsertStatement.new
statement2.columns = %w[a b c]
statement2.values = %w[x y z]
+ statement2.comment = Arel::Nodes::Comment.new(["comment"])
array = [statement1, statement2]
assert_equal 1, array.uniq.size
end
@@ -34,9 +36,15 @@ describe Arel::Nodes::InsertStatement do
statement1 = Arel::Nodes::InsertStatement.new
statement1.columns = %w[a b c]
statement1.values = %w[x y z]
+ statement1.comment = Arel::Nodes::Comment.new(["comment"])
statement2 = Arel::Nodes::InsertStatement.new
statement2.columns = %w[a b c]
statement2.values = %w[1 2 3]
+ statement2.comment = Arel::Nodes::Comment.new(["comment"])
+ array = [statement1, statement2]
+ assert_equal 2, array.uniq.size
+ statement2.values = %w[x y z]
+ statement2.comment = Arel::Nodes::Comment.new("other")
array = [statement1, statement2]
assert_equal 2, array.uniq.size
end
diff --git a/activerecord/test/cases/arel/nodes/select_core_test.rb b/activerecord/test/cases/arel/nodes/select_core_test.rb
index 0b698205ff..6860f2a395 100644
--- a/activerecord/test/cases/arel/nodes/select_core_test.rb
+++ b/activerecord/test/cases/arel/nodes/select_core_test.rb
@@ -37,6 +37,7 @@ module Arel
core1.groups = %w[j k l]
core1.windows = %w[m n o]
core1.havings = %w[p q r]
+ core1.comment = Arel::Nodes::Comment.new(["comment"])
core2 = SelectCore.new
core2.froms = %w[a b c]
core2.projections = %w[d e f]
@@ -44,6 +45,7 @@ module Arel
core2.groups = %w[j k l]
core2.windows = %w[m n o]
core2.havings = %w[p q r]
+ core2.comment = Arel::Nodes::Comment.new(["comment"])
array = [core1, core2]
assert_equal 1, array.uniq.size
end
@@ -56,6 +58,7 @@ module Arel
core1.groups = %w[j k l]
core1.windows = %w[m n o]
core1.havings = %w[p q r]
+ core1.comment = Arel::Nodes::Comment.new(["comment"])
core2 = SelectCore.new
core2.froms = %w[a b c]
core2.projections = %w[d e f]
@@ -63,6 +66,11 @@ module Arel
core2.groups = %w[j k l]
core2.windows = %w[m n o]
core2.havings = %w[l o l]
+ core2.comment = Arel::Nodes::Comment.new(["comment"])
+ array = [core1, core2]
+ assert_equal 2, array.uniq.size
+ core2.havings = %w[p q r]
+ core2.comment = Arel::Nodes::Comment.new(["other"])
array = [core1, core2]
assert_equal 2, array.uniq.size
end
diff --git a/activerecord/test/cases/arel/nodes/update_statement_test.rb b/activerecord/test/cases/arel/nodes/update_statement_test.rb
index a83ce32f68..f133ddf7eb 100644
--- a/activerecord/test/cases/arel/nodes/update_statement_test.rb
+++ b/activerecord/test/cases/arel/nodes/update_statement_test.rb
@@ -27,6 +27,7 @@ describe Arel::Nodes::UpdateStatement do
statement1.orders = %w[x y z]
statement1.limit = 42
statement1.key = "zomg"
+ statement1.comment = Arel::Nodes::Comment.new(["comment"])
statement2 = Arel::Nodes::UpdateStatement.new
statement2.relation = "zomg"
statement2.wheres = 2
@@ -34,6 +35,7 @@ describe Arel::Nodes::UpdateStatement do
statement2.orders = %w[x y z]
statement2.limit = 42
statement2.key = "zomg"
+ statement2.comment = Arel::Nodes::Comment.new(["comment"])
array = [statement1, statement2]
assert_equal 1, array.uniq.size
end
@@ -46,6 +48,7 @@ describe Arel::Nodes::UpdateStatement do
statement1.orders = %w[x y z]
statement1.limit = 42
statement1.key = "zomg"
+ statement1.comment = Arel::Nodes::Comment.new(["comment"])
statement2 = Arel::Nodes::UpdateStatement.new
statement2.relation = "zomg"
statement2.wheres = 2
@@ -53,6 +56,11 @@ describe Arel::Nodes::UpdateStatement do
statement2.orders = %w[x y z]
statement2.limit = 42
statement2.key = "wth"
+ statement2.comment = Arel::Nodes::Comment.new(["comment"])
+ array = [statement1, statement2]
+ assert_equal 2, array.uniq.size
+ statement2.key = "zomg"
+ statement2.comment = Arel::Nodes::Comment.new(["other"])
array = [statement1, statement2]
assert_equal 2, array.uniq.size
end
diff --git a/activerecord/test/cases/arel/select_manager_test.rb b/activerecord/test/cases/arel/select_manager_test.rb
index 5220950905..e6c49cd429 100644
--- a/activerecord/test/cases/arel/select_manager_test.rb
+++ b/activerecord/test/cases/arel/select_manager_test.rb
@@ -1221,5 +1221,28 @@ module Arel
manager.distinct_on(false).must_equal manager
end
end
+
+ describe "comment" do
+ it "chains" do
+ manager = Arel::SelectManager.new
+ manager.comment("selecting").must_equal manager
+ end
+
+ it "appends a comment to the generated query" do
+ manager = Arel::SelectManager.new
+ table = Table.new :users
+ manager.from(table).project(table["id"])
+
+ manager.comment("selecting")
+ manager.to_sql.must_be_like %{
+ SELECT "users"."id" FROM "users" /* selecting */
+ }
+
+ manager.comment("selecting", "with", "comment")
+ manager.to_sql.must_be_like %{
+ SELECT "users"."id" FROM "users" /* selecting */ /* with */ /* comment */
+ }
+ end
+ end
end
end
diff --git a/activerecord/test/cases/arel/support/fake_record.rb b/activerecord/test/cases/arel/support/fake_record.rb
index 559ff5d4e6..18e6c10c9d 100644
--- a/activerecord/test/cases/arel/support/fake_record.rb
+++ b/activerecord/test/cases/arel/support/fake_record.rb
@@ -58,6 +58,10 @@ module FakeRecord
"\"#{name}\""
end
+ def sanitize_as_sql_comment(comment)
+ comment
+ end
+
def schema_cache
self
end
diff --git a/activerecord/test/cases/arel/update_manager_test.rb b/activerecord/test/cases/arel/update_manager_test.rb
index cc1b9ac5b3..e13cb6aa52 100644
--- a/activerecord/test/cases/arel/update_manager_test.rb
+++ b/activerecord/test/cases/arel/update_manager_test.rb
@@ -122,5 +122,29 @@ module Arel
@um.key.must_equal @table[:foo]
end
end
+
+ describe "comment" do
+ it "chains" do
+ manager = Arel::UpdateManager.new
+ manager.comment("updating").must_equal manager
+ end
+
+ it "appends a comment to the generated query" do
+ table = Table.new :users
+
+ manager = Arel::UpdateManager.new
+ manager.table table
+
+ manager.comment("updating")
+ manager.to_sql.must_be_like %{
+ UPDATE "users" /* updating */
+ }
+
+ manager.comment("updating", "with", "comment")
+ manager.to_sql.must_be_like %{
+ UPDATE "users" /* updating */ /* with */ /* comment */
+ }
+ end
+ end
end
end
diff --git a/activerecord/test/cases/arel/visitors/depth_first_test.rb b/activerecord/test/cases/arel/visitors/depth_first_test.rb
index 4a57608411..106be2311d 100644
--- a/activerecord/test/cases/arel/visitors/depth_first_test.rb
+++ b/activerecord/test/cases/arel/visitors/depth_first_test.rb
@@ -101,6 +101,12 @@ module Arel
assert_equal [:a, :b, join], @collector.calls
end
+ def test_comment
+ comment = Nodes::Comment.new ["foo"]
+ @visitor.accept comment
+ assert_equal ["foo", ["foo"], comment], @collector.calls
+ end
+
[
Arel::Nodes::Assignment,
Arel::Nodes::Between,
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index 081da95df7..84130ec208 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -21,6 +21,11 @@ require "models/molecule"
require "models/electron"
require "models/man"
require "models/interest"
+require "models/pirate"
+require "models/parrot"
+require "models/bird"
+require "models/treasure"
+require "models/price_estimate"
class AssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
@@ -368,3 +373,97 @@ class GeneratedMethodsTest < ActiveRecord::TestCase
assert_equal :none, MyArticle.new.comments
end
end
+
+class WithAnnotationsTest < ActiveRecord::TestCase
+ fixtures :pirates, :parrots
+
+ def test_belongs_to_with_annotation_includes_a_query_comment
+ pirate = SpacePirate.where.not(parrot_id: nil).first
+ assert pirate, "should have a Pirate record"
+
+ log = capture_sql do
+ pirate.parrot
+ end
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+
+ assert_sql(%r{/\* that tells jokes \*/}) do
+ pirate.parrot_with_annotation
+ end
+ end
+
+ def test_has_and_belongs_to_many_with_annotation_includes_a_query_comment
+ pirate = SpacePirate.first
+ assert pirate, "should have a Pirate record"
+
+ log = capture_sql do
+ pirate.parrots.first
+ end
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+
+ assert_sql(%r{/\* that are very colorful \*/}) do
+ pirate.parrots_with_annotation.first
+ end
+ end
+
+ def test_has_one_with_annotation_includes_a_query_comment
+ pirate = SpacePirate.first
+ assert pirate, "should have a Pirate record"
+
+ log = capture_sql do
+ pirate.ship
+ end
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+
+ assert_sql(%r{/\* that is a rocket \*/}) do
+ pirate.ship_with_annotation
+ end
+ end
+
+ def test_has_many_with_annotation_includes_a_query_comment
+ pirate = SpacePirate.first
+ assert pirate, "should have a Pirate record"
+
+ log = capture_sql do
+ pirate.birds.first
+ end
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+
+ assert_sql(%r{/\* that are also parrots \*/}) do
+ pirate.birds_with_annotation.first
+ end
+ end
+
+ def test_has_many_through_with_annotation_includes_a_query_comment
+ pirate = SpacePirate.first
+ assert pirate, "should have a Pirate record"
+
+ log = capture_sql do
+ pirate.treasure_estimates.first
+ end
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+
+ assert_sql(%r{/\* yarrr \*/}) do
+ pirate.treasure_estimates_with_annotation.first
+ end
+ end
+
+ def test_has_many_through_with_annotation_includes_a_query_comment_when_eager_loading
+ pirate = SpacePirate.first
+ assert pirate, "should have a Pirate record"
+
+ log = capture_sql do
+ pirate.treasure_estimates.first
+ end
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+
+ assert_sql(%r{/\* yarrr \*/}) do
+ SpacePirate.includes(:treasure_estimates_with_annotation, :treasures).first
+ end
+ end
+end
diff --git a/activerecord/test/cases/relation/delete_all_test.rb b/activerecord/test/cases/relation/delete_all_test.rb
index d1c13fa1b5..9b76936b7e 100644
--- a/activerecord/test/cases/relation/delete_all_test.rb
+++ b/activerecord/test/cases/relation/delete_all_test.rb
@@ -99,4 +99,23 @@ class DeleteAllTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::RecordNotFound) { posts(:thinking) }
assert posts(:welcome)
end
+
+ def test_delete_all_with_annotation_includes_a_query_comment
+ davids = Author.where(name: "David").annotate("deleting all")
+
+ assert_sql(%r{/\* deleting all \*/}) do
+ assert_difference("Author.count", -1) { davids.delete_all }
+ end
+ end
+
+ def test_delete_all_without_annotation_does_not_include_an_empty_comment
+ davids = Author.where(name: "David")
+
+ log = capture_sql do
+ assert_difference("Author.count", -1) { davids.delete_all }
+ end
+
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+ end
end
diff --git a/activerecord/test/cases/relation/merging_test.rb b/activerecord/test/cases/relation/merging_test.rb
index 224e4f39a8..5c5e760e34 100644
--- a/activerecord/test/cases/relation/merging_test.rb
+++ b/activerecord/test/cases/relation/merging_test.rb
@@ -135,6 +135,18 @@ class RelationMergingTest < ActiveRecord::TestCase
relation = Post.all.merge(Post.order(Arel.sql("title LIKE '%?'")))
assert_equal ["title LIKE '%?'"], relation.order_values
end
+
+ def test_merging_annotations_respects_merge_order
+ assert_sql(%r{/\* foo \*/ /\* bar \*/}) do
+ Post.annotate("foo").merge(Post.annotate("bar")).first
+ end
+ assert_sql(%r{/\* bar \*/ /\* foo \*/}) do
+ Post.annotate("bar").merge(Post.annotate("foo")).first
+ end
+ assert_sql(%r{/\* foo \*/ /\* bar \*/ /\* baz \*/ /\* qux \*/}) do
+ Post.annotate("foo").annotate("bar").merge(Post.annotate("baz").annotate("qux")).first
+ end
+ end
end
class MergingDifferentRelationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/relation/update_all_test.rb b/activerecord/test/cases/relation/update_all_test.rb
index 0500574f28..526f926841 100644
--- a/activerecord/test/cases/relation/update_all_test.rb
+++ b/activerecord/test/cases/relation/update_all_test.rb
@@ -241,6 +241,33 @@ class UpdateAllTest < ActiveRecord::TestCase
end
end
+ def test_update_all_with_annotation_includes_a_query_comment
+ tag = Tag.first
+
+ assert_sql(%r{/\* updating all \*/}) do
+ Post.tagged_with(tag.id).annotate("updating all").update_all(title: "rofl")
+ end
+
+ posts = Post.tagged_with(tag.id).all.to_a
+ assert_operator posts.length, :>, 0
+ posts.each { |post| assert_equal "rofl", post.title }
+ end
+
+ def test_update_all_without_annotation_does_not_include_an_empty_comment
+ tag = Tag.first
+
+ log = capture_sql do
+ Post.tagged_with(tag.id).update_all(title: "rofl")
+ end
+
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+
+ posts = Post.tagged_with(tag.id).all.to_a
+ assert_operator posts.length, :>, 0
+ posts.each { |post| assert_equal "rofl", post.title }
+ end
+
# Oracle UPDATE does not support ORDER BY
unless current_adapter?(:OracleAdapter)
def test_update_all_ignores_order_without_limit_from_association
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 68161f6a84..00a7b3841f 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -307,6 +307,58 @@ module ActiveRecord
assert_equal 3, ratings.count
end
+ def test_relation_with_annotation_includes_comment_in_to_sql
+ post_with_annotation = Post.where(id: 1).annotate("foo")
+ assert_match %r{= 1 /\* foo \*/}, post_with_annotation.to_sql
+ end
+
+ def test_relation_with_annotation_includes_comment_in_sql
+ post_with_annotation = Post.where(id: 1).annotate("foo")
+ assert_sql(%r{/\* foo \*/}) do
+ assert post_with_annotation.first, "record should be found"
+ end
+ end
+
+ def test_relation_with_annotation_chains_sql_comments
+ post_with_annotation = Post.where(id: 1).annotate("foo").annotate("bar")
+ assert_sql(%r{/\* foo \*/ /\* bar \*/}) do
+ assert post_with_annotation.first, "record should be found"
+ end
+ end
+
+ def test_relation_with_annotation_filters_sql_comment_delimiters
+ post_with_annotation = Post.where(id: 1).annotate("**//foo//**")
+ assert_match %r{= 1 /\* foo \*/}, post_with_annotation.to_sql
+ end
+
+ def test_relation_with_annotation_includes_comment_in_count_query
+ post_with_annotation = Post.annotate("foo")
+ all_count = Post.all.to_a.count
+ assert_sql(%r{/\* foo \*/}) do
+ assert_equal all_count, post_with_annotation.count
+ end
+ end
+
+ def test_relation_without_annotation_does_not_include_an_empty_comment
+ log = capture_sql do
+ Post.where(id: 1).first
+ end
+
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
+ end
+
+ def test_relation_with_optimizer_hints_filters_sql_comment_delimiters
+ post_with_hint = Post.where(id: 1).optimizer_hints("**//BADHINT//**")
+ assert_match %r{BADHINT}, post_with_hint.to_sql
+ assert_no_match %r{\*/BADHINT}, post_with_hint.to_sql
+ assert_no_match %r{\*//BADHINT}, post_with_hint.to_sql
+ assert_no_match %r{BADHINT/\*}, post_with_hint.to_sql
+ assert_no_match %r{BADHINT//\*}, post_with_hint.to_sql
+ post_with_hint = Post.where(id: 1).optimizer_hints("/*+ BADHINT */")
+ assert_match %r{/\*\+ BADHINT \*/}, post_with_hint.to_sql
+ end
+
class EnsureRoundTripTypeCasting < ActiveRecord::Type::Value
def type
:string
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index 8b08e40468..3488442cab 100644
--- a/activerecord/test/cases/scoping/named_scoping_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -602,4 +602,14 @@ class NamedScopingTest < ActiveRecord::TestCase
Topic.create!
assert_predicate Topic, :one?
end
+
+ def test_scope_with_annotation
+ Topic.class_eval do
+ scope :including_annotate_in_scope, Proc.new { annotate("from-scope") }
+ end
+
+ assert_sql(%r{/\* from-scope \*/}) do
+ assert Topic.including_annotate_in_scope.to_a, Topic.all.to_a
+ end
+ end
end
diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb
index b1f2ffe29c..a95ab0f429 100644
--- a/activerecord/test/cases/scoping/relation_scoping_test.rb
+++ b/activerecord/test/cases/scoping/relation_scoping_test.rb
@@ -130,6 +130,44 @@ class RelationScopingTest < ActiveRecord::TestCase
end
end
+ def test_scoped_find_with_annotation
+ Developer.annotate("scoped").scoping do
+ developer = nil
+ assert_sql(%r{/\* scoped \*/}) do
+ developer = Developer.where("name = 'David'").first
+ end
+ assert_equal "David", developer.name
+ end
+ end
+
+ def test_find_with_annotation_unscoped
+ Developer.annotate("scoped").unscoped do
+ developer = nil
+ log = capture_sql do
+ developer = Developer.where("name = 'David'").first
+ end
+
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\* scoped \*/}) }, :empty?
+
+ assert_equal "David", developer.name
+ end
+ end
+
+ def test_find_with_annotation_unscope
+ developer = nil
+ log = capture_sql do
+ developer = Developer.annotate("unscope").
+ where("name = 'David'").
+ unscope(:annotate).first
+ end
+
+ assert_not_predicate log, :empty?
+ assert_predicate log.select { |query| query.match?(%r{/\* unscope \*/}) }, :empty?
+
+ assert_equal "David", developer.name
+ end
+
def test_scoped_find_include
# with the include, will retrieve only developers for the given project
scoped_developers = Developer.includes(:projects).scoping do