activerecord 7.0.4.3 → 7.0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +318 -7
- data/README.rdoc +2 -2
- data/lib/active_record/associations/collection_association.rb +1 -1
- data/lib/active_record/associations/collection_proxy.rb +5 -0
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations.rb +15 -6
- data/lib/active_record/attribute_methods/read.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -4
- data/lib/active_record/attribute_methods.rb +5 -7
- data/lib/active_record/callbacks.rb +12 -14
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +20 -16
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -1
- data/lib/active_record/connection_adapters/abstract_adapter.rb +4 -17
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +15 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -5
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -4
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/locking/optimistic.rb +32 -18
- data/lib/active_record/middleware/database_selector.rb +3 -3
- data/lib/active_record/migration/command_recorder.rb +1 -2
- data/lib/active_record/migration/compatibility.rb +19 -54
- data/lib/active_record/migration.rb +53 -4
- data/lib/active_record/persistence.rb +7 -5
- data/lib/active_record/railties/controller_runtime.rb +3 -4
- data/lib/active_record/reflection.rb +8 -0
- data/lib/active_record/relation/calculations.rb +50 -23
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -1
- data/lib/active_record/relation/query_attribute.rb +23 -0
- data/lib/active_record/relation/query_methods.rb +35 -8
- data/lib/active_record/result.rb +6 -4
- data/lib/active_record/schema_dumper.rb +4 -0
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/table_metadata.rb +6 -2
- data/lib/active_record/transactions.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -4
- data/lib/arel/filter_predications.rb +1 -1
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/filter.rb +1 -1
- metadata +13 -13
|
@@ -138,11 +138,6 @@ module ActiveRecord
|
|
|
138
138
|
true
|
|
139
139
|
end
|
|
140
140
|
|
|
141
|
-
def field_ordered_value(column, values) # :nodoc:
|
|
142
|
-
field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse.map { |value| Arel::Nodes.build_quoted(value) }])
|
|
143
|
-
Arel::Nodes::Descending.new(field)
|
|
144
|
-
end
|
|
145
|
-
|
|
146
141
|
def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
|
|
147
142
|
query_value("SELECT GET_LOCK(#{quote(lock_name.to_s)}, #{timeout})") == 1
|
|
148
143
|
end
|
|
@@ -403,7 +398,7 @@ module ActiveRecord
|
|
|
403
398
|
|
|
404
399
|
fk_info.map do |row|
|
|
405
400
|
options = {
|
|
406
|
-
column: row["column"],
|
|
401
|
+
column: unquote_identifier(row["column"]),
|
|
407
402
|
name: row["name"],
|
|
408
403
|
primary_key: row["primary_key"]
|
|
409
404
|
}
|
|
@@ -411,7 +406,7 @@ module ActiveRecord
|
|
|
411
406
|
options[:on_update] = extract_foreign_key_action(row["on_update"])
|
|
412
407
|
options[:on_delete] = extract_foreign_key_action(row["on_delete"])
|
|
413
408
|
|
|
414
|
-
ForeignKeyDefinition.new(table_name, row["to_table"], options)
|
|
409
|
+
ForeignKeyDefinition.new(table_name, unquote_identifier(row["to_table"]), options)
|
|
415
410
|
end
|
|
416
411
|
end
|
|
417
412
|
|
|
@@ -438,7 +433,8 @@ module ActiveRecord
|
|
|
438
433
|
name: row["name"]
|
|
439
434
|
}
|
|
440
435
|
expression = row["expression"]
|
|
441
|
-
expression = expression[1..-2]
|
|
436
|
+
expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
|
|
437
|
+
expression = strip_whitespace_characters(expression)
|
|
442
438
|
CheckConstraintDefinition.new(table_name, expression, options)
|
|
443
439
|
end
|
|
444
440
|
else
|
|
@@ -619,6 +615,16 @@ module ActiveRecord
|
|
|
619
615
|
end
|
|
620
616
|
|
|
621
617
|
private
|
|
618
|
+
def strip_whitespace_characters(expression)
|
|
619
|
+
expression = expression.gsub(/\\n|\\\\/, "")
|
|
620
|
+
expression = expression.gsub(/\s{2,}/, " ")
|
|
621
|
+
expression
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def text_type?(type)
|
|
625
|
+
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
|
|
626
|
+
end
|
|
627
|
+
|
|
622
628
|
def type_map
|
|
623
629
|
emulate_booleans ? TYPE_MAP_WITH_BOOLEAN : TYPE_MAP
|
|
624
630
|
end
|
|
@@ -712,7 +718,7 @@ module ActiveRecord
|
|
|
712
718
|
end
|
|
713
719
|
|
|
714
720
|
unless options.key?(:collation)
|
|
715
|
-
options[:collation] = column.collation
|
|
721
|
+
options[:collation] = column.collation if text_type?(type)
|
|
716
722
|
end
|
|
717
723
|
|
|
718
724
|
unless options.key?(:auto_increment)
|
|
@@ -6,6 +6,9 @@ module ActiveRecord
|
|
|
6
6
|
module ConnectionAdapters
|
|
7
7
|
module MySQL
|
|
8
8
|
module Quoting # :nodoc:
|
|
9
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
|
10
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
|
11
|
+
|
|
9
12
|
def quote_bound_value(value)
|
|
10
13
|
case value
|
|
11
14
|
when Rational
|
|
@@ -24,11 +27,11 @@ module ActiveRecord
|
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
def quote_column_name(name)
|
|
27
|
-
|
|
30
|
+
QUOTED_COLUMN_NAMES[name] ||= "`#{super.gsub('`', '``')}`"
|
|
28
31
|
end
|
|
29
32
|
|
|
30
33
|
def quote_table_name(name)
|
|
31
|
-
|
|
34
|
+
QUOTED_TABLE_NAMES[name] ||= super.gsub(".", "`.`").freeze
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
def unquoted_true
|
|
@@ -51,6 +54,14 @@ module ActiveRecord
|
|
|
51
54
|
"x'#{value.hex}'"
|
|
52
55
|
end
|
|
53
56
|
|
|
57
|
+
def unquote_identifier(identifier)
|
|
58
|
+
if identifier && identifier.start_with?("`")
|
|
59
|
+
identifier[1..-2]
|
|
60
|
+
else
|
|
61
|
+
identifier
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
54
65
|
# Override +type_cast+ we pass to mysql2 Date and Time objects instead
|
|
55
66
|
# of Strings since mysql2 is able to handle those classes more efficiently.
|
|
56
67
|
def type_cast(value) # :nodoc:
|
|
@@ -57,11 +57,7 @@ module ActiveRecord
|
|
|
57
57
|
fields.each_with_index do |fname, i|
|
|
58
58
|
ftype = result.ftype i
|
|
59
59
|
fmod = result.fmod i
|
|
60
|
-
|
|
61
|
-
when Type::Integer, Type::Float, OID::Decimal, Type::String, Type::DateTime, Type::Boolean
|
|
62
|
-
# skip if a column has already been type casted by pg decoders
|
|
63
|
-
else types[fname] = type
|
|
64
|
-
end
|
|
60
|
+
types[fname] = types[i] = get_oid_type(ftype, fmod, fname)
|
|
65
61
|
end
|
|
66
62
|
build_result(columns: fields, rows: result.values, column_types: types)
|
|
67
63
|
end
|
|
@@ -13,7 +13,7 @@ module ActiveRecord
|
|
|
13
13
|
return if value.blank?
|
|
14
14
|
|
|
15
15
|
time = super
|
|
16
|
-
return time if time.is_a?(ActiveSupport::TimeWithZone)
|
|
16
|
+
return time if time.is_a?(ActiveSupport::TimeWithZone) || !time.acts_like?(:time)
|
|
17
17
|
|
|
18
18
|
# While in UTC mode, the PG gem may not return times back in "UTC" even if they were provided to Postgres in UTC.
|
|
19
19
|
# We prefer times always in UTC, so here we convert back.
|
|
@@ -4,6 +4,9 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module PostgreSQL
|
|
6
6
|
module Quoting
|
|
7
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
|
8
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
|
9
|
+
|
|
7
10
|
class IntegerOutOf64BitRange < StandardError
|
|
8
11
|
def initialize(msg)
|
|
9
12
|
super(msg)
|
|
@@ -81,7 +84,7 @@ module ActiveRecord
|
|
|
81
84
|
# - "schema.name".table_name
|
|
82
85
|
# - "schema.name"."table.name"
|
|
83
86
|
def quote_table_name(name) # :nodoc:
|
|
84
|
-
|
|
87
|
+
QUOTED_TABLE_NAMES[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
|
|
85
88
|
end
|
|
86
89
|
|
|
87
90
|
# Quotes schema names for use in SQL queries.
|
|
@@ -95,7 +98,7 @@ module ActiveRecord
|
|
|
95
98
|
|
|
96
99
|
# Quotes column names for use in SQL queries.
|
|
97
100
|
def quote_column_name(name) # :nodoc:
|
|
98
|
-
|
|
101
|
+
QUOTED_COLUMN_NAMES[name] ||= PG::Connection.quote_ident(super).freeze
|
|
99
102
|
end
|
|
100
103
|
|
|
101
104
|
# Quote date/time values for use in SQL input.
|
|
@@ -498,7 +498,7 @@ module ActiveRecord
|
|
|
498
498
|
|
|
499
499
|
fk_info.map do |row|
|
|
500
500
|
options = {
|
|
501
|
-
column: row["column"],
|
|
501
|
+
column: Utils.unquote_identifier(row["column"]),
|
|
502
502
|
name: row["name"],
|
|
503
503
|
primary_key: row["primary_key"]
|
|
504
504
|
}
|
|
@@ -508,8 +508,9 @@ module ActiveRecord
|
|
|
508
508
|
options[:deferrable] = extract_foreign_key_deferrable(row["deferrable"], row["deferred"])
|
|
509
509
|
|
|
510
510
|
options[:validate] = row["valid"]
|
|
511
|
+
to_table = Utils.unquote_identifier(row["to_table"])
|
|
511
512
|
|
|
512
|
-
ForeignKeyDefinition.new(table_name,
|
|
513
|
+
ForeignKeyDefinition.new(table_name, to_table, options)
|
|
513
514
|
end
|
|
514
515
|
end
|
|
515
516
|
|
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
|
12
12
|
attr_reader :schema, :identifier
|
|
13
13
|
|
|
14
14
|
def initialize(schema, identifier)
|
|
15
|
-
@schema, @identifier =
|
|
15
|
+
@schema, @identifier = Utils.unquote_identifier(schema), Utils.unquote_identifier(identifier)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def to_s
|
|
@@ -40,15 +40,6 @@ module ActiveRecord
|
|
|
40
40
|
def parts
|
|
41
41
|
@parts ||= [@schema, @identifier].compact
|
|
42
42
|
end
|
|
43
|
-
|
|
44
|
-
private
|
|
45
|
-
def unquote(part)
|
|
46
|
-
if part && part.start_with?('"')
|
|
47
|
-
part[1..-2]
|
|
48
|
-
else
|
|
49
|
-
part
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
43
|
end
|
|
53
44
|
|
|
54
45
|
module Utils # :nodoc:
|
|
@@ -74,6 +65,14 @@ module ActiveRecord
|
|
|
74
65
|
end
|
|
75
66
|
PostgreSQL::Name.new(schema, table)
|
|
76
67
|
end
|
|
68
|
+
|
|
69
|
+
def unquote_identifier(identifier)
|
|
70
|
+
if identifier && identifier.start_with?('"')
|
|
71
|
+
identifier[1..-2]
|
|
72
|
+
else
|
|
73
|
+
identifier
|
|
74
|
+
end
|
|
75
|
+
end
|
|
77
76
|
end
|
|
78
77
|
end
|
|
79
78
|
end
|
|
@@ -977,7 +977,7 @@ module ActiveRecord
|
|
|
977
977
|
PG::TextDecoder::TimestampUtc :
|
|
978
978
|
PG::TextDecoder::TimestampWithoutTimeZone
|
|
979
979
|
|
|
980
|
-
@timestamp_decoder = decoder_class.new(
|
|
980
|
+
@timestamp_decoder = decoder_class.new(**@timestamp_decoder.to_h)
|
|
981
981
|
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
|
982
982
|
|
|
983
983
|
@default_timezone = ActiveRecord.default_timezone
|
|
@@ -4,6 +4,9 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module SQLite3
|
|
6
6
|
module Quoting # :nodoc:
|
|
7
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
|
8
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
|
9
|
+
|
|
7
10
|
def quote_string(s)
|
|
8
11
|
@connection.class.quote(s)
|
|
9
12
|
end
|
|
@@ -13,11 +16,11 @@ module ActiveRecord
|
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
def quote_table_name(name)
|
|
16
|
-
|
|
19
|
+
QUOTED_TABLE_NAMES[name] ||= super.gsub(".", "\".\"").freeze
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
def quote_column_name(name)
|
|
20
|
-
|
|
23
|
+
QUOTED_COLUMN_NAMES[name] ||= %Q("#{super.gsub('"', '""')}")
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
def quoted_time(value)
|
|
@@ -4,6 +4,12 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module SQLite3
|
|
6
6
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
|
7
|
+
def change_column(column_name, type, **options)
|
|
8
|
+
name = column_name.to_s
|
|
9
|
+
@columns_hash[name] = nil
|
|
10
|
+
column(name, type, **options)
|
|
11
|
+
end
|
|
12
|
+
|
|
7
13
|
def references(*args, **options)
|
|
8
14
|
super(*args, type: :integer, **options)
|
|
9
15
|
end
|
|
@@ -84,11 +84,11 @@ module ActiveRecord
|
|
|
84
84
|
table_sql = query_value(<<-SQL, "SCHEMA")
|
|
85
85
|
SELECT sql
|
|
86
86
|
FROM sqlite_master
|
|
87
|
-
WHERE name = #{
|
|
87
|
+
WHERE name = #{quote(table_name)} AND type = 'table'
|
|
88
88
|
UNION ALL
|
|
89
89
|
SELECT sql
|
|
90
90
|
FROM sqlite_temp_master
|
|
91
|
-
WHERE name = #{
|
|
91
|
+
WHERE name = #{quote(table_name)} AND type = 'table'
|
|
92
92
|
SQL
|
|
93
93
|
|
|
94
94
|
table_sql.to_s.scan(/CONSTRAINT\s+(?<name>\w+)\s+CHECK\s+\((?<expression>(:?[^()]|\(\g<expression>\))+)\)/i).map do |name, expression|
|
|
@@ -287,10 +287,7 @@ module ActiveRecord
|
|
|
287
287
|
|
|
288
288
|
def change_column(table_name, column_name, type, **options) # :nodoc:
|
|
289
289
|
alter_table(table_name) do |definition|
|
|
290
|
-
definition
|
|
291
|
-
self.type = aliased_types(type.to_s, type)
|
|
292
|
-
self.options.merge!(options)
|
|
293
|
-
end
|
|
290
|
+
definition.change_column(column_name, type, **options)
|
|
294
291
|
end
|
|
295
292
|
end
|
|
296
293
|
|
|
@@ -480,6 +477,7 @@ module ActiveRecord
|
|
|
480
477
|
if column.has_default?
|
|
481
478
|
type = lookup_cast_type_from_column(column)
|
|
482
479
|
default = type.deserialize(column.default)
|
|
480
|
+
default = -> { column.default_function } if default.nil?
|
|
483
481
|
end
|
|
484
482
|
|
|
485
483
|
@definition.column(column_name, column.type,
|
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
|
21
21
|
# On the other hand, we want to monitor the performance of our real database
|
|
22
22
|
# queries, not the performance of the access to the query cache.
|
|
23
23
|
IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
|
|
24
|
-
EXPLAINED_SQLS = /\A\s*(with|select|update|delete|insert)\b/i
|
|
24
|
+
EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
|
|
25
25
|
def ignore_payload?(payload)
|
|
26
26
|
payload[:exception] ||
|
|
27
27
|
payload[:cached] ||
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module Locking
|
|
5
|
-
# == What is Optimistic Locking
|
|
5
|
+
# == What is \Optimistic \Locking
|
|
6
6
|
#
|
|
7
7
|
# Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
|
|
8
8
|
# conflicts with the data. It does this by checking whether another process has made changes to a record since
|
|
9
|
-
# it was opened, an
|
|
9
|
+
# it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
|
|
10
10
|
# and the update is ignored.
|
|
11
11
|
#
|
|
12
|
-
# Check out
|
|
12
|
+
# Check out +ActiveRecord::Locking::Pessimistic+ for an alternative.
|
|
13
13
|
#
|
|
14
14
|
# == Usage
|
|
15
15
|
#
|
|
@@ -69,6 +69,11 @@ module ActiveRecord
|
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
def initialize_dup(other) # :nodoc:
|
|
73
|
+
super
|
|
74
|
+
_clear_locking_column if locking_enabled?
|
|
75
|
+
end
|
|
76
|
+
|
|
72
77
|
private
|
|
73
78
|
def _create_record(attribute_names = self.attribute_names)
|
|
74
79
|
if locking_enabled?
|
|
@@ -91,8 +96,7 @@ module ActiveRecord
|
|
|
91
96
|
locking_column = self.class.locking_column
|
|
92
97
|
lock_attribute_was = @attributes[locking_column]
|
|
93
98
|
|
|
94
|
-
update_constraints =
|
|
95
|
-
update_constraints[locking_column] = _lock_value_for_database(locking_column)
|
|
99
|
+
update_constraints = _query_constraints_hash
|
|
96
100
|
|
|
97
101
|
attribute_names = attribute_names.dup if attribute_names.frozen?
|
|
98
102
|
attribute_names << locking_column
|
|
@@ -118,16 +122,9 @@ module ActiveRecord
|
|
|
118
122
|
end
|
|
119
123
|
|
|
120
124
|
def destroy_row
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
locking_column = self.class.locking_column
|
|
125
|
+
affected_rows = super
|
|
124
126
|
|
|
125
|
-
|
|
126
|
-
delete_constraints[locking_column] = _lock_value_for_database(locking_column)
|
|
127
|
-
|
|
128
|
-
affected_rows = self.class._delete_record(delete_constraints)
|
|
129
|
-
|
|
130
|
-
if affected_rows != 1
|
|
127
|
+
if locking_enabled? && affected_rows != 1
|
|
131
128
|
raise ActiveRecord::StaleObjectError.new(self, "destroy")
|
|
132
129
|
end
|
|
133
130
|
|
|
@@ -142,6 +139,18 @@ module ActiveRecord
|
|
|
142
139
|
end
|
|
143
140
|
end
|
|
144
141
|
|
|
142
|
+
def _clear_locking_column
|
|
143
|
+
self[self.class.locking_column] = nil
|
|
144
|
+
clear_attribute_change(self.class.locking_column)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def _query_constraints_hash
|
|
148
|
+
return super unless locking_enabled?
|
|
149
|
+
|
|
150
|
+
locking_column = self.class.locking_column
|
|
151
|
+
super.merge(locking_column => _lock_value_for_database(locking_column))
|
|
152
|
+
end
|
|
153
|
+
|
|
145
154
|
module ClassMethods
|
|
146
155
|
DEFAULT_LOCKING_COLUMN = "lock_version"
|
|
147
156
|
|
|
@@ -159,10 +168,7 @@ module ActiveRecord
|
|
|
159
168
|
end
|
|
160
169
|
|
|
161
170
|
# The version column used for optimistic locking. Defaults to +lock_version+.
|
|
162
|
-
|
|
163
|
-
@locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
|
|
164
|
-
@locking_column
|
|
165
|
-
end
|
|
171
|
+
attr_reader :locking_column
|
|
166
172
|
|
|
167
173
|
# Reset the column used for optimistic locking back to the +lock_version+ default.
|
|
168
174
|
def reset_locking_column
|
|
@@ -182,6 +188,14 @@ module ActiveRecord
|
|
|
182
188
|
end
|
|
183
189
|
super
|
|
184
190
|
end
|
|
191
|
+
|
|
192
|
+
private
|
|
193
|
+
def inherited(base)
|
|
194
|
+
super
|
|
195
|
+
base.class_eval do
|
|
196
|
+
@locking_column = DEFAULT_LOCKING_COLUMN
|
|
197
|
+
end
|
|
198
|
+
end
|
|
185
199
|
end
|
|
186
200
|
end
|
|
187
201
|
|
|
@@ -43,9 +43,9 @@ module ActiveRecord
|
|
|
43
43
|
# config.active_record.database_resolver = MyResolver
|
|
44
44
|
# config.active_record.database_resolver_context = MyResolver::MySession
|
|
45
45
|
#
|
|
46
|
-
# Note: If you are using
|
|
47
|
-
#
|
|
48
|
-
#
|
|
46
|
+
# Note: If you are using <tt>rails new my_app --minimal</tt> you will need
|
|
47
|
+
# to call <tt>require "active_support/core_ext/integer/time"</tt> to load
|
|
48
|
+
# the core extension in order to use +2.seconds+
|
|
49
49
|
class DatabaseSelector
|
|
50
50
|
def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
|
|
51
51
|
@app = app
|
|
@@ -12,7 +12,6 @@ module ActiveRecord
|
|
|
12
12
|
# * add_index
|
|
13
13
|
# * add_reference
|
|
14
14
|
# * add_timestamps
|
|
15
|
-
# * change_column
|
|
16
15
|
# * change_column_default (must supply a +:from+ and +:to+ option)
|
|
17
16
|
# * change_column_null
|
|
18
17
|
# * change_column_comment (must supply a +:from+ and +:to+ option)
|
|
@@ -24,7 +23,7 @@ module ActiveRecord
|
|
|
24
23
|
# * drop_table (must supply a block)
|
|
25
24
|
# * enable_extension
|
|
26
25
|
# * remove_column (must supply a type)
|
|
27
|
-
# * remove_columns (must
|
|
26
|
+
# * remove_columns (must supply a +:type+ option)
|
|
28
27
|
# * remove_foreign_key (must supply a second table)
|
|
29
28
|
# * remove_check_constraint
|
|
30
29
|
# * remove_index
|
|
@@ -56,12 +56,13 @@ module ActiveRecord
|
|
|
56
56
|
super
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
def
|
|
60
|
-
if
|
|
61
|
-
|
|
62
|
-
else
|
|
63
|
-
super
|
|
59
|
+
def change_column(table_name, column_name, type, **options)
|
|
60
|
+
if type == :datetime
|
|
61
|
+
options[:precision] ||= nil
|
|
64
62
|
end
|
|
63
|
+
|
|
64
|
+
type = PostgreSQLCompat.compatible_timestamp_type(type, connection)
|
|
65
|
+
super
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
module TableDefinition
|
|
@@ -70,6 +71,11 @@ module ActiveRecord
|
|
|
70
71
|
super
|
|
71
72
|
end
|
|
72
73
|
|
|
74
|
+
def change(name, type, index: nil, **options)
|
|
75
|
+
options[:precision] ||= nil
|
|
76
|
+
super
|
|
77
|
+
end
|
|
78
|
+
|
|
73
79
|
def column(name, type, index: nil, **options)
|
|
74
80
|
options[:precision] ||= nil
|
|
75
81
|
super
|
|
@@ -81,7 +87,7 @@ module ActiveRecord
|
|
|
81
87
|
class << t
|
|
82
88
|
prepend TableDefinition
|
|
83
89
|
end
|
|
84
|
-
|
|
90
|
+
super
|
|
85
91
|
end
|
|
86
92
|
end
|
|
87
93
|
|
|
@@ -105,30 +111,6 @@ module ActiveRecord
|
|
|
105
111
|
end
|
|
106
112
|
end
|
|
107
113
|
|
|
108
|
-
def create_table(table_name, **options)
|
|
109
|
-
if block_given?
|
|
110
|
-
super { |t| yield compatible_table_definition(t) }
|
|
111
|
-
else
|
|
112
|
-
super
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def change_table(table_name, **options)
|
|
117
|
-
if block_given?
|
|
118
|
-
super { |t| yield compatible_table_definition(t) }
|
|
119
|
-
else
|
|
120
|
-
super
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def create_join_table(table_1, table_2, **options)
|
|
125
|
-
if block_given?
|
|
126
|
-
super { |t| yield compatible_table_definition(t) }
|
|
127
|
-
else
|
|
128
|
-
super
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
114
|
def add_reference(table_name, ref_name, **options)
|
|
133
115
|
if connection.adapter_name == "SQLite"
|
|
134
116
|
options[:type] = :integer
|
|
@@ -159,6 +141,13 @@ module ActiveRecord
|
|
|
159
141
|
options[:precision] ||= nil
|
|
160
142
|
super
|
|
161
143
|
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
def raise_on_if_exist_options(options)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def raise_on_duplicate_column(name)
|
|
150
|
+
end
|
|
162
151
|
end
|
|
163
152
|
|
|
164
153
|
module CommandRecorder
|
|
@@ -175,30 +164,6 @@ module ActiveRecord
|
|
|
175
164
|
end
|
|
176
165
|
end
|
|
177
166
|
|
|
178
|
-
def create_table(table_name, **options)
|
|
179
|
-
if block_given?
|
|
180
|
-
super { |t| yield compatible_table_definition(t) }
|
|
181
|
-
else
|
|
182
|
-
super
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def change_table(table_name, **options)
|
|
187
|
-
if block_given?
|
|
188
|
-
super { |t| yield compatible_table_definition(t) }
|
|
189
|
-
else
|
|
190
|
-
super
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def create_join_table(table_1, table_2, **options)
|
|
195
|
-
if block_given?
|
|
196
|
-
super { |t| yield compatible_table_definition(t) }
|
|
197
|
-
else
|
|
198
|
-
super
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
167
|
def add_timestamps(table_name, **options)
|
|
203
168
|
options[:precision] ||= nil
|
|
204
169
|
super
|