activerecord 6.0.0.beta2 → 6.0.2.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +471 -9
  3. data/README.rdoc +3 -1
  4. data/lib/active_record.rb +0 -1
  5. data/lib/active_record/association_relation.rb +15 -6
  6. data/lib/active_record/associations.rb +4 -3
  7. data/lib/active_record/associations/association.rb +10 -2
  8. data/lib/active_record/associations/builder/association.rb +14 -18
  9. data/lib/active_record/associations/builder/belongs_to.rb +5 -2
  10. data/lib/active_record/associations/builder/collection_association.rb +5 -15
  11. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -1
  12. data/lib/active_record/associations/builder/has_many.rb +2 -0
  13. data/lib/active_record/associations/builder/has_one.rb +35 -1
  14. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  15. data/lib/active_record/associations/collection_association.rb +6 -2
  16. data/lib/active_record/associations/collection_proxy.rb +2 -2
  17. data/lib/active_record/associations/has_many_through_association.rb +4 -11
  18. data/lib/active_record/associations/join_dependency.rb +14 -9
  19. data/lib/active_record/associations/join_dependency/join_association.rb +12 -3
  20. data/lib/active_record/associations/preloader.rb +13 -8
  21. data/lib/active_record/associations/preloader/association.rb +34 -30
  22. data/lib/active_record/associations/preloader/through_association.rb +48 -28
  23. data/lib/active_record/attribute_methods.rb +3 -53
  24. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
  25. data/lib/active_record/attribute_methods/dirty.rb +47 -14
  26. data/lib/active_record/attribute_methods/primary_key.rb +7 -15
  27. data/lib/active_record/attribute_methods/query.rb +2 -3
  28. data/lib/active_record/attribute_methods/read.rb +3 -9
  29. data/lib/active_record/attribute_methods/write.rb +6 -12
  30. data/lib/active_record/attributes.rb +13 -0
  31. data/lib/active_record/autosave_association.rb +21 -7
  32. data/lib/active_record/base.rb +0 -1
  33. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +109 -11
  34. data/lib/active_record/connection_adapters/abstract/database_limits.rb +8 -4
  35. data/lib/active_record/connection_adapters/abstract/database_statements.rb +88 -61
  36. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -4
  37. data/lib/active_record/connection_adapters/abstract/quoting.rb +63 -6
  38. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -7
  39. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
  40. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +79 -22
  41. data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -4
  42. data/lib/active_record/connection_adapters/abstract_adapter.rb +114 -34
  43. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +78 -73
  44. data/lib/active_record/connection_adapters/column.rb +17 -13
  45. data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
  46. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
  47. data/lib/active_record/connection_adapters/mysql/database_statements.rb +48 -8
  48. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  49. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -5
  50. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +10 -7
  51. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  52. data/lib/active_record/connection_adapters/mysql2_adapter.rb +18 -5
  53. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -30
  54. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -2
  55. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  56. data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
  57. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +34 -38
  58. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +23 -27
  59. data/lib/active_record/connection_adapters/postgresql_adapter.rb +68 -27
  60. data/lib/active_record/connection_adapters/schema_cache.rb +32 -14
  61. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  62. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  63. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -2
  64. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
  65. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +66 -114
  66. data/lib/active_record/connection_handling.rb +31 -13
  67. data/lib/active_record/core.rb +23 -24
  68. data/lib/active_record/database_configurations.rb +73 -44
  69. data/lib/active_record/database_configurations/hash_config.rb +11 -11
  70. data/lib/active_record/database_configurations/url_config.rb +12 -12
  71. data/lib/active_record/dynamic_matchers.rb +1 -1
  72. data/lib/active_record/enum.rb +15 -0
  73. data/lib/active_record/errors.rb +1 -1
  74. data/lib/active_record/fixtures.rb +11 -6
  75. data/lib/active_record/gem_version.rb +2 -2
  76. data/lib/active_record/insert_all.rb +179 -0
  77. data/lib/active_record/integration.rb +13 -1
  78. data/lib/active_record/internal_metadata.rb +5 -1
  79. data/lib/active_record/locking/optimistic.rb +3 -4
  80. data/lib/active_record/log_subscriber.rb +1 -1
  81. data/lib/active_record/middleware/database_selector.rb +3 -3
  82. data/lib/active_record/middleware/database_selector/resolver.rb +4 -6
  83. data/lib/active_record/migration.rb +62 -44
  84. data/lib/active_record/migration/command_recorder.rb +28 -14
  85. data/lib/active_record/migration/compatibility.rb +10 -0
  86. data/lib/active_record/model_schema.rb +3 -0
  87. data/lib/active_record/persistence.rb +206 -13
  88. data/lib/active_record/querying.rb +17 -12
  89. data/lib/active_record/railtie.rb +0 -1
  90. data/lib/active_record/railties/databases.rake +127 -25
  91. data/lib/active_record/reflection.rb +3 -3
  92. data/lib/active_record/relation.rb +99 -20
  93. data/lib/active_record/relation/calculations.rb +38 -40
  94. data/lib/active_record/relation/delegation.rb +22 -30
  95. data/lib/active_record/relation/finder_methods.rb +17 -12
  96. data/lib/active_record/relation/merger.rb +11 -16
  97. data/lib/active_record/relation/query_methods.rb +228 -76
  98. data/lib/active_record/relation/where_clause.rb +9 -5
  99. data/lib/active_record/sanitization.rb +33 -4
  100. data/lib/active_record/schema.rb +1 -1
  101. data/lib/active_record/schema_dumper.rb +10 -1
  102. data/lib/active_record/schema_migration.rb +1 -1
  103. data/lib/active_record/scoping/default.rb +6 -7
  104. data/lib/active_record/scoping/named.rb +3 -2
  105. data/lib/active_record/statement_cache.rb +2 -2
  106. data/lib/active_record/store.rb +48 -0
  107. data/lib/active_record/table_metadata.rb +9 -13
  108. data/lib/active_record/tasks/database_tasks.rb +109 -6
  109. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -1
  110. data/lib/active_record/test_databases.rb +1 -16
  111. data/lib/active_record/test_fixtures.rb +1 -0
  112. data/lib/active_record/timestamp.rb +26 -16
  113. data/lib/active_record/touch_later.rb +4 -2
  114. data/lib/active_record/transactions.rb +56 -46
  115. data/lib/active_record/type_caster/connection.rb +16 -10
  116. data/lib/active_record/validations.rb +1 -0
  117. data/lib/active_record/validations/uniqueness.rb +3 -5
  118. data/lib/arel.rb +12 -5
  119. data/lib/arel/insert_manager.rb +3 -3
  120. data/lib/arel/nodes.rb +2 -1
  121. data/lib/arel/nodes/comment.rb +29 -0
  122. data/lib/arel/nodes/select_core.rb +16 -12
  123. data/lib/arel/nodes/unary.rb +1 -0
  124. data/lib/arel/nodes/values_list.rb +2 -17
  125. data/lib/arel/select_manager.rb +10 -10
  126. data/lib/arel/visitors/depth_first.rb +7 -2
  127. data/lib/arel/visitors/dot.rb +7 -2
  128. data/lib/arel/visitors/ibm_db.rb +13 -0
  129. data/lib/arel/visitors/informix.rb +6 -0
  130. data/lib/arel/visitors/mssql.rb +15 -1
  131. data/lib/arel/visitors/oracle12.rb +4 -5
  132. data/lib/arel/visitors/postgresql.rb +4 -10
  133. data/lib/arel/visitors/to_sql.rb +107 -131
  134. data/lib/arel/visitors/visitor.rb +9 -5
  135. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  136. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  137. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  138. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  139. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  140. metadata +16 -12
  141. data/lib/active_record/collection_cache_key.rb +0 -53
  142. data/lib/arel/nodes/values.rb +0 -16
@@ -17,17 +17,17 @@ module ActiveRecord
17
17
  # @config={"adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost"},
18
18
  # @url="postgres://localhost/foo">
19
19
  #
20
- # Options are:
20
+ # ==== Options
21
21
  #
22
- # <tt>:env_name</tt> - The Rails environment, ie "development"
23
- # <tt>:spec_name</tt> - The specification name. In a standard two-tier
24
- # database configuration this will default to "primary". In a multiple
25
- # database three-tier database configuration this corresponds to the name
26
- # used in the second tier, for example "primary_readonly".
27
- # <tt>:url</tt> - The database URL.
28
- # <tt>:config</tt> - The config hash. This is the hash that contains the
29
- # database adapter, name, and other important information for database
30
- # connections.
22
+ # * <tt>:env_name</tt> - The Rails environment, ie "development".
23
+ # * <tt>:spec_name</tt> - The specification name. In a standard two-tier
24
+ # database configuration this will default to "primary". In a multiple
25
+ # database three-tier database configuration this corresponds to the name
26
+ # used in the second tier, for example "primary_readonly".
27
+ # * <tt>:url</tt> - The database URL.
28
+ # * <tt>:config</tt> - The config hash. This is the hash that contains the
29
+ # database adapter, name, and other important information for database
30
+ # connections.
31
31
  class UrlConfig < DatabaseConfig
32
32
  attr_reader :url, :config
33
33
 
@@ -42,14 +42,14 @@ module ActiveRecord
42
42
  end
43
43
 
44
44
  # Determines whether a database configuration is for a replica / readonly
45
- # connection. If the `replica` key is present in the config, `replica?` will
45
+ # connection. If the +replica+ key is present in the config, +replica?+ will
46
46
  # return +true+.
47
47
  def replica?
48
48
  config["replica"]
49
49
  end
50
50
 
51
51
  # The migrations paths for a database configuration. If the
52
- # `migrations_paths` key is present in the config, `migrations_paths`
52
+ # +migrations_paths+ key is present in the config, +migrations_paths+
53
53
  # will return its value.
54
54
  def migrations_paths
55
55
  config["migrations_paths"]
@@ -53,7 +53,7 @@ module ActiveRecord
53
53
  @model = model
54
54
  @name = name.to_s
55
55
  @attribute_names = @name.match(self.class.pattern)[1].split("_and_")
56
- @attribute_names.map! { |n| @model.attribute_aliases[n] || n }
56
+ @attribute_names.map! { |name| @model.attribute_aliases[name] || name }
57
57
  end
58
58
 
59
59
  def valid?
@@ -31,7 +31,9 @@ module ActiveRecord
31
31
  # as well. With the above example:
32
32
  #
33
33
  # Conversation.active
34
+ # Conversation.not_active
34
35
  # Conversation.archived
36
+ # Conversation.not_archived
35
37
  #
36
38
  # Of course, you can also query them directly if the scopes don't fit your
37
39
  # needs:
@@ -196,9 +198,15 @@ module ActiveRecord
196
198
  define_method("#{value_method_name}!") { update!(attr => value) }
197
199
 
198
200
  # scope :active, -> { where(status: 0) }
201
+ # scope :not_active, -> { where.not(status: 0) }
199
202
  if enum_scopes != false
203
+ klass.send(:detect_negative_condition!, value_method_name)
204
+
200
205
  klass.send(:detect_enum_conflict!, name, value_method_name, true)
201
206
  klass.scope value_method_name, -> { where(attr => value) }
207
+
208
+ klass.send(:detect_enum_conflict!, name, "not_#{value_method_name}", true)
209
+ klass.scope "not_#{value_method_name}", -> { where.not(attr => value) }
202
210
  end
203
211
  end
204
212
  end
@@ -255,5 +263,12 @@ module ActiveRecord
255
263
  source: source
256
264
  }
257
265
  end
266
+
267
+ def detect_negative_condition!(method_name)
268
+ if method_name.start_with?("not_") && logger
269
+ logger.warn "An enum element in #{self.name} uses the prefix 'not_'." \
270
+ " This will cause a conflict with auto generated negative scopes."
271
+ end
272
+ end
258
273
  end
259
274
  end
@@ -68,7 +68,7 @@ module ActiveRecord
68
68
 
69
69
  # Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
70
70
  # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
71
- # methods when a record is invalid and can not be saved.
71
+ # methods when a record is invalid and cannot be saved.
72
72
  class RecordNotSaved < ActiveRecordError
73
73
  attr_reader :record
74
74
 
@@ -531,15 +531,15 @@ module ActiveRecord
531
531
  end
532
532
  end
533
533
 
534
- def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
534
+ def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
535
535
  fixture_set_names = Array(fixture_set_names).map(&:to_s)
536
536
  class_names = ClassCache.new class_names, config
537
537
 
538
538
  # FIXME: Apparently JK uses this.
539
- connection = block_given? ? yield : ActiveRecord::Base.connection
539
+ connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
540
540
 
541
541
  fixture_files_to_read = fixture_set_names.reject do |fs_name|
542
- fixture_is_cached?(connection, fs_name)
542
+ fixture_is_cached?(connection.call, fs_name)
543
543
  end
544
544
 
545
545
  if fixture_files_to_read.any?
@@ -549,9 +549,9 @@ module ActiveRecord
549
549
  class_names,
550
550
  connection,
551
551
  )
552
- cache_fixtures(connection, fixtures_map)
552
+ cache_fixtures(connection.call, fixtures_map)
553
553
  end
554
- cached_fixtures(connection, fixture_set_names)
554
+ cached_fixtures(connection.call, fixture_set_names)
555
555
  end
556
556
 
557
557
  # Returns a consistent, platform-independent identifier for +label+.
@@ -591,7 +591,11 @@ module ActiveRecord
591
591
 
592
592
  def insert(fixture_sets, connection) # :nodoc:
593
593
  fixture_sets_by_connection = fixture_sets.group_by do |fixture_set|
594
- fixture_set.model_class&.connection || connection
594
+ if fixture_set.model_class
595
+ fixture_set.model_class.connection
596
+ else
597
+ connection.call
598
+ end
595
599
  end
596
600
 
597
601
  fixture_sets_by_connection.each do |conn, set|
@@ -602,6 +606,7 @@ module ActiveRecord
602
606
  table_rows_for_connection[table].unshift(*rows)
603
607
  end
604
608
  end
609
+
605
610
  conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
606
611
 
607
612
  # Cap primary key sequences to max(pk).
@@ -9,8 +9,8 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 6
11
11
  MINOR = 0
12
- TINY = 0
13
- PRE = "beta2"
12
+ TINY = 2
13
+ PRE = "rc1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class InsertAll # :nodoc:
5
+ attr_reader :model, :connection, :inserts, :keys
6
+ attr_reader :on_duplicate, :returning, :unique_by
7
+
8
+ def initialize(model, inserts, on_duplicate:, returning: nil, unique_by: nil)
9
+ raise ArgumentError, "Empty list of attributes passed" if inserts.blank?
10
+
11
+ @model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s).to_set
12
+ @on_duplicate, @returning, @unique_by = on_duplicate, returning, unique_by
13
+
14
+ @returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
15
+ @returning = false if @returning == []
16
+
17
+ @unique_by = find_unique_index_for(unique_by) if unique_by
18
+ @on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
19
+
20
+ ensure_valid_options_for_connection!
21
+ end
22
+
23
+ def execute
24
+ message = +"#{model} "
25
+ message << "Bulk " if inserts.many?
26
+ message << (on_duplicate == :update ? "Upsert" : "Insert")
27
+ connection.exec_insert_all to_sql, message
28
+ end
29
+
30
+ def updatable_columns
31
+ keys - readonly_columns - unique_by_columns
32
+ end
33
+
34
+ def primary_keys
35
+ Array(model.primary_key)
36
+ end
37
+
38
+
39
+ def skip_duplicates?
40
+ on_duplicate == :skip
41
+ end
42
+
43
+ def update_duplicates?
44
+ on_duplicate == :update
45
+ end
46
+
47
+ def map_key_with_value
48
+ inserts.map do |attributes|
49
+ attributes = attributes.stringify_keys
50
+ verify_attributes(attributes)
51
+
52
+ keys.map do |key|
53
+ yield key, attributes[key]
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+ def find_unique_index_for(unique_by)
60
+ match = Array(unique_by).map(&:to_s)
61
+
62
+ if index = unique_indexes.find { |i| match.include?(i.name) || i.columns == match }
63
+ index
64
+ else
65
+ raise ArgumentError, "No unique index found for #{unique_by}"
66
+ end
67
+ end
68
+
69
+ def unique_indexes
70
+ connection.schema_cache.indexes(model.table_name).select(&:unique)
71
+ end
72
+
73
+
74
+ def ensure_valid_options_for_connection!
75
+ if returning && !connection.supports_insert_returning?
76
+ raise ArgumentError, "#{connection.class} does not support :returning"
77
+ end
78
+
79
+ if skip_duplicates? && !connection.supports_insert_on_duplicate_skip?
80
+ raise ArgumentError, "#{connection.class} does not support skipping duplicates"
81
+ end
82
+
83
+ if update_duplicates? && !connection.supports_insert_on_duplicate_update?
84
+ raise ArgumentError, "#{connection.class} does not support upsert"
85
+ end
86
+
87
+ if unique_by && !connection.supports_insert_conflict_target?
88
+ raise ArgumentError, "#{connection.class} does not support :unique_by"
89
+ end
90
+ end
91
+
92
+
93
+ def to_sql
94
+ connection.build_insert_sql(ActiveRecord::InsertAll::Builder.new(self))
95
+ end
96
+
97
+
98
+ def readonly_columns
99
+ primary_keys + model.readonly_attributes.to_a
100
+ end
101
+
102
+ def unique_by_columns
103
+ Array(unique_by&.columns)
104
+ end
105
+
106
+
107
+ def verify_attributes(attributes)
108
+ if keys != attributes.keys.to_set
109
+ raise ArgumentError, "All objects being inserted must have the same keys"
110
+ end
111
+ end
112
+
113
+ class Builder # :nodoc:
114
+ attr_reader :model
115
+
116
+ delegate :skip_duplicates?, :update_duplicates?, :keys, to: :insert_all
117
+
118
+ def initialize(insert_all)
119
+ @insert_all, @model, @connection = insert_all, insert_all.model, insert_all.connection
120
+ end
121
+
122
+ def into
123
+ "INTO #{model.quoted_table_name}(#{columns_list})"
124
+ end
125
+
126
+ def values_list
127
+ types = extract_types_from_columns_on(model.table_name, keys: keys)
128
+
129
+ values_list = insert_all.map_key_with_value do |key, value|
130
+ connection.with_yaml_fallback(types[key].serialize(value))
131
+ end
132
+
133
+ Arel::InsertManager.new.create_values_list(values_list).to_sql
134
+ end
135
+
136
+ def returning
137
+ format_columns(insert_all.returning) if insert_all.returning
138
+ end
139
+
140
+ def conflict_target
141
+ if index = insert_all.unique_by
142
+ sql = +"(#{format_columns(index.columns)})"
143
+ sql << " WHERE #{index.where}" if index.where
144
+ sql
145
+ elsif update_duplicates?
146
+ "(#{format_columns(insert_all.primary_keys)})"
147
+ end
148
+ end
149
+
150
+ def updatable_columns
151
+ quote_columns(insert_all.updatable_columns)
152
+ end
153
+
154
+ private
155
+ attr_reader :connection, :insert_all
156
+
157
+ def columns_list
158
+ format_columns(insert_all.keys)
159
+ end
160
+
161
+ def extract_types_from_columns_on(table_name, keys:)
162
+ columns = connection.schema_cache.columns_hash(table_name)
163
+
164
+ unknown_column = (keys - columns.keys).first
165
+ raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
166
+
167
+ keys.map { |key| [ key, connection.lookup_cast_type_from_column(columns[key]) ] }.to_h
168
+ end
169
+
170
+ def format_columns(columns)
171
+ quote_columns(columns).join(",")
172
+ end
173
+
174
+ def quote_columns(columns)
175
+ columns.map(&connection.method(:quote_column_name))
176
+ end
177
+ end
178
+ end
179
+ end
@@ -22,6 +22,14 @@ module ActiveRecord
22
22
  #
23
23
  # This is +true+, by default on Rails 5.2 and above.
24
24
  class_attribute :cache_versioning, instance_writer: false, default: false
25
+
26
+ ##
27
+ # :singleton-method:
28
+ # Indicates whether to use a stable #cache_key method that is accompanied
29
+ # by a changing version in the #cache_version method on collections.
30
+ #
31
+ # This is +false+, by default until Rails 6.1.
32
+ class_attribute :collection_cache_versioning, instance_writer: false, default: false
25
33
  end
26
34
 
27
35
  # Returns a +String+, which Action Pack uses for constructing a URL to this
@@ -152,6 +160,10 @@ module ActiveRecord
152
160
  end
153
161
  end
154
162
  end
163
+
164
+ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
165
+ collection.send(:compute_cache_key, timestamp_column)
166
+ end
155
167
  end
156
168
 
157
169
  private
@@ -180,7 +192,7 @@ module ActiveRecord
180
192
  # raw_timestamp_to_cache_version(timestamp)
181
193
  # # => "20181015200215266505"
182
194
  #
183
- # Postgres truncates trailing zeros,
195
+ # PostgreSQL truncates trailing zeros,
184
196
  # https://github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214
185
197
  # to account for this we pad the output with zeros
186
198
  def raw_timestamp_to_cache_version(timestamp)
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  end
18
18
 
19
19
  def table_name
20
- "#{table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{table_name_suffix}"
20
+ "#{table_name_prefix}#{internal_metadata_table_name}#{table_name_suffix}"
21
21
  end
22
22
 
23
23
  def []=(key, value)
@@ -44,6 +44,10 @@ module ActiveRecord
44
44
  end
45
45
  end
46
46
  end
47
+
48
+ def drop_table
49
+ connection.drop_table table_name, if_exists: true
50
+ end
47
51
  end
48
52
  end
49
53
  end
@@ -71,9 +71,8 @@ module ActiveRecord
71
71
  end
72
72
 
73
73
  def _touch_row(attribute_names, time)
74
+ @_touch_attr_names << self.class.locking_column if locking_enabled?
74
75
  super
75
- ensure
76
- clear_attribute_change(self.class.locking_column) if locking_enabled?
77
76
  end
78
77
 
79
78
  def _update_row(attribute_names, attempted_action = "update")
@@ -88,7 +87,7 @@ module ActiveRecord
88
87
 
89
88
  affected_rows = self.class._update_record(
90
89
  attributes_with_values(attribute_names),
91
- self.class.primary_key => id_in_database,
90
+ @primary_key => id_in_database,
92
91
  locking_column => previous_lock_value
93
92
  )
94
93
 
@@ -111,7 +110,7 @@ module ActiveRecord
111
110
  locking_column = self.class.locking_column
112
111
 
113
112
  affected_rows = self.class._delete_record(
114
- self.class.primary_key => id_in_database,
113
+ @primary_key => id_in_database,
115
114
  locking_column => read_attribute_before_type_cast(locking_column)
116
115
  )
117
116
 
@@ -110,7 +110,7 @@ module ActiveRecord
110
110
  end
111
111
 
112
112
  def extract_query_source_location(locations)
113
- backtrace_cleaner.clean(locations).first
113
+ backtrace_cleaner.clean(locations.lazy).first
114
114
  end
115
115
  end
116
116
  end
@@ -35,10 +35,10 @@ module ActiveRecord
35
35
  # config.active_record.database_resolver = MyResolver
36
36
  # config.active_record.database_resolver_context = MyResolver::MySession
37
37
  class DatabaseSelector
38
- def initialize(app, resolver_klass = Resolver, context_klass = Resolver::Session, options = {})
38
+ def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
39
39
  @app = app
40
- @resolver_klass = resolver_klass
41
- @context_klass = context_klass
40
+ @resolver_klass = resolver_klass || Resolver
41
+ @context_klass = context_klass || Resolver::Session
42
42
  @options = options
43
43
  end
44
44