1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #30980 from sobrinho/sobrinho/arel-star-ignored-columns

Do not use `Arel.star` when `ignored_columns`
This commit is contained in:
Rafael França 2017-11-13 15:27:59 -05:00 committed by GitHub
commit f49d59432a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 45 deletions

View file

@ -1038,6 +1038,8 @@ module ActiveRecord
def build_select(arel)
if select_values.any?
arel.project(*arel_columns(select_values.uniq))
elsif @klass.ignored_columns.any?
arel.project(*arel_columns(@klass.column_names))
else
arel.project(table[Arel.star])
end

View file

@ -1,23 +1,23 @@
# frozen_string_literal: true
require "cases/helper"
require "models/developer"
require "models/computer"
require "models/author"
require "models/post"
class Mysql2ExplainTest < ActiveRecord::Mysql2TestCase
fixtures :developers
fixtures :authors
def test_explain_for_one_query
explain = Developer.where(id: 1).explain
assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain
assert_match %r(developers |.* const), explain
explain = Author.where(id: 1).explain
assert_match %(EXPLAIN for: SELECT `authors`.* FROM `authors` WHERE `authors`.`id` = 1), explain
assert_match %r(authors |.* const), explain
end
def test_explain_with_eager_loading
explain = Developer.where(id: 1).includes(:audit_logs).explain
assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain
assert_match %r(developers |.* const), explain
assert_match %(EXPLAIN for: SELECT `audit_logs`.* FROM `audit_logs` WHERE `audit_logs`.`developer_id` = 1), explain
assert_match %r(audit_logs |.* ALL), explain
explain = Author.where(id: 1).includes(:posts).explain
assert_match %(EXPLAIN for: SELECT `authors`.* FROM `authors` WHERE `authors`.`id` = 1), explain
assert_match %r(authors |.* const), explain
assert_match %(EXPLAIN for: SELECT `posts`.* FROM `posts` WHERE `posts`.`author_id` = 1), explain
assert_match %r(posts |.* ALL), explain
end
end

View file

@ -1,22 +1,22 @@
# frozen_string_literal: true
require "cases/helper"
require "models/developer"
require "models/computer"
require "models/author"
require "models/post"
class PostgreSQLExplainTest < ActiveRecord::PostgreSQLTestCase
fixtures :developers
fixtures :authors
def test_explain_for_one_query
explain = Developer.where(id: 1).explain
assert_match %r(EXPLAIN for: SELECT "developers"\.\* FROM "developers" WHERE "developers"\."id" = (?:\$1 \[\["id", 1\]\]|1)), explain
explain = Author.where(id: 1).explain
assert_match %r(EXPLAIN for: SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\$1 \[\["id", 1\]\]|1)), explain
assert_match %(QUERY PLAN), explain
end
def test_explain_with_eager_loading
explain = Developer.where(id: 1).includes(:audit_logs).explain
explain = Author.where(id: 1).includes(:posts).explain
assert_match %(QUERY PLAN), explain
assert_match %r(EXPLAIN for: SELECT "developers"\.\* FROM "developers" WHERE "developers"\."id" = (?:\$1 \[\["id", 1\]\]|1)), explain
assert_match %r(EXPLAIN for: SELECT "audit_logs"\.\* FROM "audit_logs" WHERE "audit_logs"\."developer_id" = (?:\$1 \[\["developer_id", 1\]\]|1)), explain
assert_match %r(EXPLAIN for: SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\$1 \[\["id", 1\]\]|1)), explain
assert_match %r(EXPLAIN for: SELECT "posts"\.\* FROM "posts" WHERE "posts"\."author_id" = (?:\$1 \[\["author_id", 1\]\]|1)), explain
end
end

View file

@ -1,23 +1,23 @@
# frozen_string_literal: true
require "cases/helper"
require "models/developer"
require "models/computer"
require "models/author"
require "models/post"
class SQLite3ExplainTest < ActiveRecord::SQLite3TestCase
fixtures :developers
fixtures :authors
def test_explain_for_one_query
explain = Developer.where(id: 1).explain
assert_match %r(EXPLAIN for: SELECT "developers"\.\* FROM "developers" WHERE "developers"\."id" = (?:\? \[\["id", 1\]\]|1)), explain
assert_match(/(SEARCH )?TABLE developers USING (INTEGER )?PRIMARY KEY/, explain)
explain = Author.where(id: 1).explain
assert_match %r(EXPLAIN for: SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\? \[\["id", 1\]\]|1)), explain
assert_match(/(SEARCH )?TABLE authors USING (INTEGER )?PRIMARY KEY/, explain)
end
def test_explain_with_eager_loading
explain = Developer.where(id: 1).includes(:audit_logs).explain
assert_match %r(EXPLAIN for: SELECT "developers"\.\* FROM "developers" WHERE "developers"\."id" = (?:\? \[\["id", 1\]\]|1)), explain
assert_match(/(SEARCH )?TABLE developers USING (INTEGER )?PRIMARY KEY/, explain)
assert_match %r(EXPLAIN for: SELECT "audit_logs"\.\* FROM "audit_logs" WHERE "audit_logs"\."developer_id" = (?:\? \[\["developer_id", 1\]\]|1)), explain
assert_match(/(SCAN )?TABLE audit_logs/, explain)
explain = Author.where(id: 1).includes(:posts).explain
assert_match %r(EXPLAIN for: SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\? \[\["id", 1\]\]|1)), explain
assert_match(/(SEARCH )?TABLE authors USING (INTEGER )?PRIMARY KEY/, explain)
assert_match %r(EXPLAIN for: SELECT "posts"\.\* FROM "posts" WHERE "posts"\."author_id" = (?:\? \[\["author_id", 1\]\]|1)), explain
assert_match(/(SCAN )?TABLE posts/, explain)
end
end

View file

@ -1476,4 +1476,25 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal(%w(first_name last_name), Developer.ignored_columns)
assert_equal(%w(first_name last_name), SymbolIgnoredDeveloper.ignored_columns)
end
test "when #reload called, ignored columns' attribute methods are not defined" do
developer = Developer.create!(name: "Developer")
refute developer.respond_to?(:first_name)
refute developer.respond_to?(:first_name=)
developer.reload
refute developer.respond_to?(:first_name)
refute developer.respond_to?(:first_name=)
end
test "ignored columns not included in SELECT" do
query = Developer.all.to_sql
# ignored column
refute query.include?("first_name")
# regular column
assert query.include?("name")
end
end

View file

@ -120,49 +120,49 @@ class DefaultScopingTest < ActiveRecord::TestCase
def test_unscope_with_where_attributes
expected = Developer.order("salary DESC").collect(&:name)
received = DeveloperOrderedBySalary.where(name: "David").unscope(where: :name).collect(&:name)
assert_equal expected, received
assert_equal expected.sort, received.sort
expected_2 = Developer.order("salary DESC").collect(&:name)
received_2 = DeveloperOrderedBySalary.select("id").where("name" => "Jamis").unscope({ where: :name }, :select).collect(&:name)
assert_equal expected_2, received_2
assert_equal expected_2.sort, received_2.sort
expected_3 = Developer.order("salary DESC").collect(&:name)
received_3 = DeveloperOrderedBySalary.select("id").where("name" => "Jamis").unscope(:select, :where).collect(&:name)
assert_equal expected_3, received_3
assert_equal expected_3.sort, received_3.sort
expected_4 = Developer.order("salary DESC").collect(&:name)
received_4 = DeveloperOrderedBySalary.where.not("name" => "Jamis").unscope(where: :name).collect(&:name)
assert_equal expected_4, received_4
assert_equal expected_4.sort, received_4.sort
expected_5 = Developer.order("salary DESC").collect(&:name)
received_5 = DeveloperOrderedBySalary.where.not("name" => ["Jamis", "David"]).unscope(where: :name).collect(&:name)
assert_equal expected_5, received_5
assert_equal expected_5.sort, received_5.sort
expected_6 = Developer.order("salary DESC").collect(&:name)
received_6 = DeveloperOrderedBySalary.where(Developer.arel_table["name"].eq("David")).unscope(where: :name).collect(&:name)
assert_equal expected_6, received_6
assert_equal expected_6.sort, received_6.sort
expected_7 = Developer.order("salary DESC").collect(&:name)
received_7 = DeveloperOrderedBySalary.where(Developer.arel_table[:name].eq("David")).unscope(where: :name).collect(&:name)
assert_equal expected_7, received_7
assert_equal expected_7.sort, received_7.sort
end
def test_unscope_comparison_where_clauses
# unscoped for WHERE (`developers`.`id` <= 2)
expected = Developer.order("salary DESC").collect(&:name)
received = DeveloperOrderedBySalary.where(id: -Float::INFINITY..2).unscope(where: :id).collect { |dev| dev.name }
assert_equal expected, received
assert_equal expected.sort, received.sort
# unscoped for WHERE (`developers`.`id` < 2)
expected = Developer.order("salary DESC").collect(&:name)
received = DeveloperOrderedBySalary.where(id: -Float::INFINITY...2).unscope(where: :id).collect { |dev| dev.name }
assert_equal expected, received
assert_equal expected.sort, received.sort
end
def test_unscope_multiple_where_clauses
expected = Developer.order("salary DESC").collect(&:name)
received = DeveloperOrderedBySalary.where(name: "Jamis").where(id: 1).unscope(where: [:name, :id]).collect(&:name)
assert_equal expected, received
assert_equal expected.sort, received.sort
end
def test_unscope_string_where_clauses_involved
@ -172,23 +172,23 @@ class DefaultScopingTest < ActiveRecord::TestCase
dev_ordered_relation = DeveloperOrderedBySalary.where(name: "Jamis").where("created_at > ?", 1.year.ago)
received = dev_ordered_relation.unscope(where: [:name]).collect(&:name)
assert_equal expected, received
assert_equal expected.sort, received.sort
end
def test_unscope_with_grouping_attributes
expected = Developer.order("salary DESC").collect(&:name)
received = DeveloperOrderedBySalary.group(:name).unscope(:group).collect(&:name)
assert_equal expected, received
assert_equal expected.sort, received.sort
expected_2 = Developer.order("salary DESC").collect(&:name)
received_2 = DeveloperOrderedBySalary.group("name").unscope(:group).collect(&:name)
assert_equal expected_2, received_2
assert_equal expected_2.sort, received_2.sort
end
def test_unscope_with_limit_in_query
expected = Developer.order("salary DESC").collect(&:name)
received = DeveloperOrderedBySalary.limit(1).unscope(:limit).collect(&:name)
assert_equal expected, received
assert_equal expected.sort, received.sort
end
def test_order_to_unscope_reordering
@ -472,7 +472,7 @@ class DefaultScopingTest < ActiveRecord::TestCase
test "a scope can remove the condition from the default scope" do
scope = DeveloperCalledJamis.david2
assert_equal 1, scope.where_clause.ast.children.length
assert_equal Developer.where(name: "David"), scope
assert_equal Developer.where(name: "David").map(&:id), scope.map(&:id)
end
def test_with_abstract_class_where_clause_should_not_be_duplicated