aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/statement_cache_test.rb
blob: 6a6d73dc38f8c57e7808770f38d0c10194d7aef0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

require "cases/helper"
require "models/book"
require "models/liquid"
require "models/molecule"
require "models/numeric_data"
require "models/electron"

module ActiveRecord
  class StatementCacheTest < ActiveRecord::TestCase
    def setup
      @connection = ActiveRecord::Base.connection
    end

    def test_statement_cache
      Book.create(name: "my book")
      Book.create(name: "my other book")

      cache = StatementCache.create(Book.connection) do |params|
        Book.where(name: params.bind)
      end

      b = cache.execute([ "my book" ], Book.connection)
      assert_equal "my book", b[0].name
      b = cache.execute([ "my other book" ], Book.connection)
      assert_equal "my other book", b[0].name
    end

    def test_statement_cache_id
      b1 = Book.create(name: "my book")
      b2 = Book.create(name: "my other book")

      cache = StatementCache.create(Book.connection) do |params|
        Book.where(id: params.bind)
      end

      b = cache.execute([ b1.id ], Book.connection)
      assert_equal b1.name, b[0].name
      b = cache.execute([ b2.id ], Book.connection)
      assert_equal b2.name, b[0].name
    end

    def test_find_or_create_by
      Book.create(name: "my book")

      a = Book.find_or_create_by(name: "my book")
      b = Book.find_or_create_by(name: "my other book")

      assert_equal("my book", a.name)
      assert_equal("my other book", b.name)
    end

    def test_statement_cache_with_simple_statement
      cache = ActiveRecord::StatementCache.create(Book.connection) do |params|
        Book.where(name: "my book").where("author_id > 3")
      end

      Book.create(name: "my book", author_id: 4)

      books = cache.execute([], Book.connection)
      assert_equal "my book", books[0].name
    end

    def test_statement_cache_with_complex_statement
      cache = ActiveRecord::StatementCache.create(Book.connection) do |params|
        Liquid.joins(molecules: :electrons).where("molecules.name" => "dioxane", "electrons.name" => "lepton")
      end

      salty = Liquid.create(name: "salty")
      molecule = salty.molecules.create(name: "dioxane")
      molecule.electrons.create(name: "lepton")

      liquids = cache.execute([], Book.connection)
      assert_equal "salty", liquids[0].name
    end

    def test_statement_cache_with_strictly_cast_attribute
      row = NumericData.create(temperature: 1.5)
      assert_equal row, NumericData.find_by(temperature: 1.5)
    end

    def test_statement_cache_values_differ
      cache = ActiveRecord::StatementCache.create(Book.connection) do |params|
        Book.where(name: "my book")
      end

      3.times do
        Book.create(name: "my book")
      end

      first_books = cache.execute([], Book.connection)

      3.times do
        Book.create(name: "my book")
      end

      additional_books = cache.execute([], Book.connection)
      assert first_books != additional_books
    end

    def test_unprepared_statements_dont_share_a_cache_with_prepared_statements
      Book.create(name: "my book")
      Book.create(name: "my other book")

      book = Book.find_by(name: "my book")
      other_book = Book.connection.unprepared_statement do
        Book.find_by(name: "my other book")
      end

      assert_not_equal book, other_book
    end

    def test_find_by_does_not_use_statement_cache_if_table_name_is_changed
      book = Book.create(name: "my book")

      Book.find_by(name: book.name) # warming the statement cache.

      # changing the table name should change the query that is not cached.
      Book.table_name = :birds
      assert_nil Book.find_by(name: book.name)
    ensure
      Book.table_name = :books
    end

    def test_find_does_not_use_statement_cache_if_table_name_is_changed
      book = Book.create(name: "my book")

      Book.find(book.id) # warming the statement cache.

      # changing the table name should change the query that is not cached.
      Book.table_name = :birds
      assert_raise ActiveRecord::RecordNotFound do
        Book.find(book.id)
      end
    ensure
      Book.table_name = :books
    end
  end
end