activerecord 4.2.6 → 5.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1307 -1105
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record/aggregations.rb +37 -23
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +11 -9
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +50 -31
- data/lib/active_record/associations/collection_proxy.rb +69 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
- data/lib/active_record/associations/join_dependency.rb +29 -19
- data/lib/active_record/associations/preloader/association.rb +46 -52
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +27 -14
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/associations.rb +317 -209
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +68 -18
- data/lib/active_record/attribute_assignment.rb +20 -141
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attributes.rb +199 -80
- data/lib/active_record/autosave_association.rb +49 -16
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -140
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +153 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -362
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -176
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +148 -203
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +89 -107
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +113 -76
- data/lib/active_record/errors.rb +87 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +364 -109
- data/lib/active_record/model_schema.rb +128 -38
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +121 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +27 -18
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +58 -45
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +282 -115
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +80 -102
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +163 -81
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -15
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/relation.rb +176 -116
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -17
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +58 -41
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -20
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -41
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +30 -29
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +7 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +58 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -50
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -105
@@ -1,13 +1,10 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
class TransactionState
|
4
|
-
attr_reader :parent
|
5
|
-
|
6
4
|
VALID_STATES = Set.new([:committed, :rolledback, nil])
|
7
5
|
|
8
6
|
def initialize(state = nil)
|
9
7
|
@state = state
|
10
|
-
@parent = nil
|
11
8
|
end
|
12
9
|
|
13
10
|
def finalized?
|
@@ -27,7 +24,7 @@ module ActiveRecord
|
|
27
24
|
end
|
28
25
|
|
29
26
|
def set_state(state)
|
30
|
-
|
27
|
+
unless VALID_STATES.include?(state)
|
31
28
|
raise ArgumentError, "Invalid transaction state: #{state}"
|
32
29
|
end
|
33
30
|
@state = state
|
@@ -36,6 +33,7 @@ module ActiveRecord
|
|
36
33
|
|
37
34
|
class NullTransaction #:nodoc:
|
38
35
|
def initialize; end
|
36
|
+
def state; end
|
39
37
|
def closed?; true; end
|
40
38
|
def open?; false; end
|
41
39
|
def joinable?; false; end
|
@@ -47,11 +45,12 @@ module ActiveRecord
|
|
47
45
|
attr_reader :connection, :state, :records, :savepoint_name
|
48
46
|
attr_writer :joinable
|
49
47
|
|
50
|
-
def initialize(connection, options)
|
48
|
+
def initialize(connection, options, run_commit_callbacks: false)
|
51
49
|
@connection = connection
|
52
50
|
@state = TransactionState.new
|
53
51
|
@records = []
|
54
52
|
@joinable = options.fetch(:joinable, true)
|
53
|
+
@run_commit_callbacks = run_commit_callbacks
|
55
54
|
end
|
56
55
|
|
57
56
|
def add_record(record)
|
@@ -65,16 +64,11 @@ module ActiveRecord
|
|
65
64
|
def rollback_records
|
66
65
|
ite = records.uniq
|
67
66
|
while record = ite.shift
|
68
|
-
|
69
|
-
record.rolledback! full_rollback?
|
70
|
-
rescue => e
|
71
|
-
raise if ActiveRecord::Base.raise_in_transactional_callbacks
|
72
|
-
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
73
|
-
end
|
67
|
+
record.rolledback!(force_restore_state: full_rollback?)
|
74
68
|
end
|
75
69
|
ensure
|
76
70
|
ite.each do |i|
|
77
|
-
i.rolledback!(full_rollback?, false)
|
71
|
+
i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
|
78
72
|
end
|
79
73
|
end
|
80
74
|
|
@@ -82,20 +76,22 @@ module ActiveRecord
|
|
82
76
|
@state.set_state(:committed)
|
83
77
|
end
|
84
78
|
|
79
|
+
def before_commit_records
|
80
|
+
records.uniq.each(&:before_committed!) if @run_commit_callbacks
|
81
|
+
end
|
82
|
+
|
85
83
|
def commit_records
|
86
84
|
ite = records.uniq
|
87
85
|
while record = ite.shift
|
88
|
-
|
86
|
+
if @run_commit_callbacks
|
89
87
|
record.committed!
|
90
|
-
|
91
|
-
|
92
|
-
record.
|
88
|
+
else
|
89
|
+
# if not running callbacks, only adds the record to the parent transaction
|
90
|
+
record.add_to_transaction
|
93
91
|
end
|
94
92
|
end
|
95
93
|
ensure
|
96
|
-
ite.each
|
97
|
-
i.committed!(false)
|
98
|
-
end
|
94
|
+
ite.each { |i| i.committed!(should_run_callbacks: false) }
|
99
95
|
end
|
100
96
|
|
101
97
|
def full_rollback?; true; end
|
@@ -106,8 +102,8 @@ module ActiveRecord
|
|
106
102
|
|
107
103
|
class SavepointTransaction < Transaction
|
108
104
|
|
109
|
-
def initialize(connection, savepoint_name, options)
|
110
|
-
super(connection, options)
|
105
|
+
def initialize(connection, savepoint_name, options, *args)
|
106
|
+
super(connection, options, *args)
|
111
107
|
if options[:isolation]
|
112
108
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
113
109
|
end
|
@@ -117,14 +113,11 @@ module ActiveRecord
|
|
117
113
|
def rollback
|
118
114
|
connection.rollback_to_savepoint(savepoint_name)
|
119
115
|
super
|
120
|
-
rollback_records
|
121
116
|
end
|
122
117
|
|
123
118
|
def commit
|
124
119
|
connection.release_savepoint(savepoint_name)
|
125
120
|
super
|
126
|
-
parent = connection.transaction_manager.current_transaction
|
127
|
-
records.each { |r| parent.add_record(r) }
|
128
121
|
end
|
129
122
|
|
130
123
|
def full_rollback?; false; end
|
@@ -132,7 +125,7 @@ module ActiveRecord
|
|
132
125
|
|
133
126
|
class RealTransaction < Transaction
|
134
127
|
|
135
|
-
def initialize(connection, options)
|
128
|
+
def initialize(connection, options, *args)
|
136
129
|
super
|
137
130
|
if options[:isolation]
|
138
131
|
connection.begin_isolated_db_transaction(options[:isolation])
|
@@ -144,13 +137,11 @@ module ActiveRecord
|
|
144
137
|
def rollback
|
145
138
|
connection.rollback_db_transaction
|
146
139
|
super
|
147
|
-
rollback_records
|
148
140
|
end
|
149
141
|
|
150
142
|
def commit
|
151
143
|
connection.commit_db_transaction
|
152
144
|
super
|
153
|
-
commit_records
|
154
145
|
end
|
155
146
|
end
|
156
147
|
|
@@ -161,29 +152,46 @@ module ActiveRecord
|
|
161
152
|
end
|
162
153
|
|
163
154
|
def begin_transaction(options = {})
|
155
|
+
run_commit_callbacks = !current_transaction.joinable?
|
164
156
|
transaction =
|
165
157
|
if @stack.empty?
|
166
|
-
RealTransaction.new(@connection, options)
|
158
|
+
RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
|
167
159
|
else
|
168
|
-
SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options
|
160
|
+
SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options,
|
161
|
+
run_commit_callbacks: run_commit_callbacks)
|
169
162
|
end
|
163
|
+
|
170
164
|
@stack.push(transaction)
|
171
165
|
transaction
|
172
166
|
end
|
173
167
|
|
174
168
|
def commit_transaction
|
175
|
-
@stack.
|
169
|
+
transaction = @stack.last
|
170
|
+
|
171
|
+
begin
|
172
|
+
transaction.before_commit_records
|
173
|
+
ensure
|
174
|
+
@stack.pop
|
175
|
+
end
|
176
|
+
|
177
|
+
transaction.commit
|
178
|
+
transaction.commit_records
|
176
179
|
end
|
177
180
|
|
178
|
-
def rollback_transaction
|
179
|
-
@stack.pop
|
181
|
+
def rollback_transaction(transaction = nil)
|
182
|
+
transaction ||= @stack.pop
|
183
|
+
transaction.rollback
|
184
|
+
transaction.rollback_records
|
180
185
|
end
|
181
186
|
|
182
187
|
def within_new_transaction(options = {})
|
183
188
|
transaction = begin_transaction options
|
184
189
|
yield
|
185
190
|
rescue Exception => error
|
186
|
-
|
191
|
+
if transaction
|
192
|
+
rollback_transaction
|
193
|
+
after_failure_actions(transaction, error)
|
194
|
+
end
|
187
195
|
raise
|
188
196
|
ensure
|
189
197
|
unless error
|
@@ -193,7 +201,7 @@ module ActiveRecord
|
|
193
201
|
begin
|
194
202
|
commit_transaction
|
195
203
|
rescue Exception
|
196
|
-
transaction
|
204
|
+
rollback_transaction(transaction) unless transaction.state.completed?
|
197
205
|
raise
|
198
206
|
end
|
199
207
|
end
|
@@ -209,7 +217,16 @@ module ActiveRecord
|
|
209
217
|
end
|
210
218
|
|
211
219
|
private
|
220
|
+
|
212
221
|
NULL_TRANSACTION = NullTransaction.new
|
222
|
+
|
223
|
+
# Deallocate invalidated prepared statements outside of the transaction
|
224
|
+
def after_failure_actions(transaction, error)
|
225
|
+
return unless transaction.is_a?(RealTransaction)
|
226
|
+
return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
|
227
|
+
@connection.clear_cache!
|
228
|
+
end
|
229
|
+
|
213
230
|
end
|
214
231
|
end
|
215
232
|
end
|
@@ -1,12 +1,9 @@
|
|
1
|
-
require 'date'
|
2
|
-
require 'bigdecimal'
|
3
|
-
require 'bigdecimal/util'
|
4
1
|
require 'active_record/type'
|
5
|
-
require '
|
2
|
+
require 'active_record/connection_adapters/determine_if_preparable_visitor'
|
6
3
|
require 'active_record/connection_adapters/schema_cache'
|
4
|
+
require 'active_record/connection_adapters/sql_type_metadata'
|
7
5
|
require 'active_record/connection_adapters/abstract/schema_dumper'
|
8
6
|
require 'active_record/connection_adapters/abstract/schema_creation'
|
9
|
-
require 'monitor'
|
10
7
|
require 'arel/collectors/bind'
|
11
8
|
require 'arel/collectors/sql_string'
|
12
9
|
|
@@ -21,15 +18,15 @@ module ActiveRecord
|
|
21
18
|
autoload :IndexDefinition
|
22
19
|
autoload :ColumnDefinition
|
23
20
|
autoload :ChangeColumnDefinition
|
21
|
+
autoload :ForeignKeyDefinition
|
24
22
|
autoload :TableDefinition
|
25
23
|
autoload :Table
|
26
24
|
autoload :AlterTable
|
27
|
-
autoload :
|
25
|
+
autoload :ReferenceDefinition
|
28
26
|
end
|
29
27
|
|
30
28
|
autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
|
31
29
|
autoload :ConnectionHandler
|
32
|
-
autoload :ConnectionManagement
|
33
30
|
end
|
34
31
|
|
35
32
|
autoload_under 'abstract' do
|
@@ -54,23 +51,23 @@ module ActiveRecord
|
|
54
51
|
# related classes form the abstraction layer which makes this possible.
|
55
52
|
# An AbstractAdapter represents a connection to a database, and provides an
|
56
53
|
# abstract interface for database-specific functionality such as establishing
|
57
|
-
# a connection, escaping values, building the right SQL fragments for
|
58
|
-
# and
|
54
|
+
# a connection, escaping values, building the right SQL fragments for +:offset+
|
55
|
+
# and +:limit+ options, etc.
|
59
56
|
#
|
60
57
|
# All the concrete database adapters follow the interface laid down in this class.
|
61
|
-
# ActiveRecord::Base.connection returns an AbstractAdapter object, which
|
58
|
+
# {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling#connection] returns an AbstractAdapter object, which
|
62
59
|
# you can use.
|
63
60
|
#
|
64
61
|
# Most of the methods in the adapter are useful during migrations. Most
|
65
|
-
# notably, the instance methods provided by
|
62
|
+
# notably, the instance methods provided by SchemaStatements are very useful.
|
66
63
|
class AbstractAdapter
|
67
64
|
ADAPTER_NAME = 'Abstract'.freeze
|
68
65
|
include Quoting, DatabaseStatements, SchemaStatements
|
69
66
|
include DatabaseLimits
|
70
67
|
include QueryCache
|
71
68
|
include ActiveSupport::Callbacks
|
72
|
-
include MonitorMixin
|
73
69
|
include ColumnDumper
|
70
|
+
include Savepoints
|
74
71
|
|
75
72
|
SIMPLE_INT = /\A\d+\z/
|
76
73
|
|
@@ -98,22 +95,43 @@ module ActiveRecord
|
|
98
95
|
|
99
96
|
attr_reader :prepared_statements
|
100
97
|
|
101
|
-
def initialize(connection, logger = nil,
|
98
|
+
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
102
99
|
super()
|
103
100
|
|
104
101
|
@connection = connection
|
105
102
|
@owner = nil
|
106
103
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
107
104
|
@logger = logger
|
108
|
-
@
|
105
|
+
@config = config
|
106
|
+
@pool = nil
|
109
107
|
@schema_cache = SchemaCache.new self
|
110
|
-
@
|
111
|
-
@
|
108
|
+
@quoted_column_names, @quoted_table_names = {}, {}
|
109
|
+
@visitor = arel_visitor
|
110
|
+
|
111
|
+
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
112
|
+
@prepared_statements = true
|
113
|
+
@visitor.extend(DetermineIfPreparableVisitor)
|
114
|
+
else
|
115
|
+
@prepared_statements = false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class Version
|
120
|
+
include Comparable
|
121
|
+
|
122
|
+
def initialize(version_string)
|
123
|
+
@version = version_string.split('.').map(&:to_i)
|
124
|
+
end
|
125
|
+
|
126
|
+
def <=>(version_string)
|
127
|
+
@version <=> version_string.split('.').map(&:to_i)
|
128
|
+
end
|
112
129
|
end
|
113
130
|
|
114
131
|
class BindCollector < Arel::Collectors::Bind
|
115
132
|
def compile(bvs, conn)
|
116
|
-
|
133
|
+
casted_binds = conn.prepare_binds_for_database(bvs)
|
134
|
+
super(casted_binds.map { |value| conn.quote(value) })
|
117
135
|
end
|
118
136
|
end
|
119
137
|
|
@@ -131,20 +149,32 @@ module ActiveRecord
|
|
131
149
|
end
|
132
150
|
end
|
133
151
|
|
152
|
+
def arel_visitor # :nodoc:
|
153
|
+
Arel::Visitors::ToSql.new(self)
|
154
|
+
end
|
155
|
+
|
134
156
|
def valid_type?(type)
|
135
|
-
|
157
|
+
false
|
136
158
|
end
|
137
159
|
|
138
160
|
def schema_creation
|
139
161
|
SchemaCreation.new self
|
140
162
|
end
|
141
163
|
|
164
|
+
# this method must only be called while holding connection pool's mutex
|
142
165
|
def lease
|
143
|
-
|
144
|
-
|
145
|
-
|
166
|
+
if in_use?
|
167
|
+
msg = 'Cannot lease connection, '
|
168
|
+
if @owner == Thread.current
|
169
|
+
msg << 'it is already leased by the current thread.'
|
170
|
+
else
|
171
|
+
msg << "it is already in use by a different thread: #{@owner}. " <<
|
172
|
+
"Current thread: #{Thread.current}."
|
146
173
|
end
|
174
|
+
raise ActiveRecordError, msg
|
147
175
|
end
|
176
|
+
|
177
|
+
@owner = Thread.current
|
148
178
|
end
|
149
179
|
|
150
180
|
def schema_cache=(cache)
|
@@ -152,6 +182,7 @@ module ActiveRecord
|
|
152
182
|
@schema_cache = cache
|
153
183
|
end
|
154
184
|
|
185
|
+
# this method must only be called while holding connection pool's mutex
|
155
186
|
def expire
|
156
187
|
@owner = nil
|
157
188
|
end
|
@@ -195,6 +226,11 @@ module ActiveRecord
|
|
195
226
|
false
|
196
227
|
end
|
197
228
|
|
229
|
+
# Does this adapter support application-enforced advisory locking?
|
230
|
+
def supports_advisory_locks?
|
231
|
+
false
|
232
|
+
end
|
233
|
+
|
198
234
|
# Should primary key values be selected from their corresponding
|
199
235
|
# sequence before the insert statement? If true, next_sequence_value
|
200
236
|
# is called before each insert to set the record's primary key.
|
@@ -212,6 +248,11 @@ module ActiveRecord
|
|
212
248
|
false
|
213
249
|
end
|
214
250
|
|
251
|
+
# Does this adapter support expression indices?
|
252
|
+
def supports_expression_index?
|
253
|
+
false
|
254
|
+
end
|
255
|
+
|
215
256
|
# Does this adapter support explain?
|
216
257
|
def supports_explain?
|
217
258
|
false
|
@@ -243,6 +284,31 @@ module ActiveRecord
|
|
243
284
|
false
|
244
285
|
end
|
245
286
|
|
287
|
+
# Does this adapter support datetime with precision?
|
288
|
+
def supports_datetime_with_precision?
|
289
|
+
false
|
290
|
+
end
|
291
|
+
|
292
|
+
# Does this adapter support json data type?
|
293
|
+
def supports_json?
|
294
|
+
false
|
295
|
+
end
|
296
|
+
|
297
|
+
# Does this adapter support metadata comments on database objects (tables, columns, indexes)?
|
298
|
+
def supports_comments?
|
299
|
+
false
|
300
|
+
end
|
301
|
+
|
302
|
+
# Can comments for tables, columns, and indexes be specified in create/alter table statements?
|
303
|
+
def supports_comments_in_create?
|
304
|
+
false
|
305
|
+
end
|
306
|
+
|
307
|
+
# Does this adapter support multi-value insert?
|
308
|
+
def supports_multi_insert?
|
309
|
+
true
|
310
|
+
end
|
311
|
+
|
246
312
|
# This is meant to be implemented by the adapters that support extensions
|
247
313
|
def disable_extension(name)
|
248
314
|
end
|
@@ -251,6 +317,20 @@ module ActiveRecord
|
|
251
317
|
def enable_extension(name)
|
252
318
|
end
|
253
319
|
|
320
|
+
# This is meant to be implemented by the adapters that support advisory
|
321
|
+
# locks
|
322
|
+
#
|
323
|
+
# Return true if we got the lock, otherwise false
|
324
|
+
def get_advisory_lock(lock_id) # :nodoc:
|
325
|
+
end
|
326
|
+
|
327
|
+
# This is meant to be implemented by the adapters that support advisory
|
328
|
+
# locks.
|
329
|
+
#
|
330
|
+
# Return true if we released the lock, otherwise false
|
331
|
+
def release_advisory_lock(lock_id) # :nodoc:
|
332
|
+
end
|
333
|
+
|
254
334
|
# A list of extensions, to be filled in by adapters that support them.
|
255
335
|
def extensions
|
256
336
|
[]
|
@@ -261,14 +341,6 @@ module ActiveRecord
|
|
261
341
|
{}
|
262
342
|
end
|
263
343
|
|
264
|
-
# QUOTING ==================================================
|
265
|
-
|
266
|
-
# Returns a bind substitution value given a bind +column+
|
267
|
-
# NOTE: The column param is currently being used by the sqlserver-adapter
|
268
|
-
def substitute_at(column, _unused = 0)
|
269
|
-
Arel::Nodes::BindParam.new
|
270
|
-
end
|
271
|
-
|
272
344
|
# REFERENTIAL INTEGRITY ====================================
|
273
345
|
|
274
346
|
# Override to turn off referential integrity while executing <tt>&block</tt>.
|
@@ -322,14 +394,14 @@ module ActiveRecord
|
|
322
394
|
end
|
323
395
|
|
324
396
|
# Checks whether the connection to the database is still active (i.e. not stale).
|
325
|
-
# This is done under the hood by calling
|
397
|
+
# This is done under the hood by calling #active?. If the connection
|
326
398
|
# is no longer active, then this method will reconnect to the database.
|
327
399
|
def verify!(*ignored)
|
328
400
|
reconnect! unless active?
|
329
401
|
end
|
330
402
|
|
331
403
|
# Provides access to the underlying database driver for this adapter. For
|
332
|
-
# example, this method returns a
|
404
|
+
# example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
|
333
405
|
# and a PGconn object in case of PostgreSQLAdapter.
|
334
406
|
#
|
335
407
|
# This is useful for when you need to call a proprietary method such as
|
@@ -338,29 +410,26 @@ module ActiveRecord
|
|
338
410
|
@connection
|
339
411
|
end
|
340
412
|
|
341
|
-
def create_savepoint(name = nil)
|
342
|
-
end
|
343
|
-
|
344
|
-
def release_savepoint(name = nil)
|
345
|
-
end
|
346
|
-
|
347
|
-
def case_sensitive_modifier(node, table_attribute)
|
348
|
-
node
|
349
|
-
end
|
350
|
-
|
351
413
|
def case_sensitive_comparison(table, attribute, column, value)
|
352
|
-
|
353
|
-
|
354
|
-
|
414
|
+
if value.nil?
|
415
|
+
table[attribute].eq(value)
|
416
|
+
else
|
417
|
+
table[attribute].eq(Arel::Nodes::BindParam.new)
|
418
|
+
end
|
355
419
|
end
|
356
420
|
|
357
421
|
def case_insensitive_comparison(table, attribute, column, value)
|
358
|
-
|
422
|
+
if can_perform_case_insensitive_comparison_for?(column)
|
423
|
+
table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new))
|
424
|
+
else
|
425
|
+
table[attribute].eq(Arel::Nodes::BindParam.new)
|
426
|
+
end
|
359
427
|
end
|
360
428
|
|
361
|
-
def
|
362
|
-
|
429
|
+
def can_perform_case_insensitive_comparison_for?(column)
|
430
|
+
true
|
363
431
|
end
|
432
|
+
private :can_perform_case_insensitive_comparison_for?
|
364
433
|
|
365
434
|
# Check the connection back in to the connection pool
|
366
435
|
def close
|
@@ -373,8 +442,8 @@ module ActiveRecord
|
|
373
442
|
end
|
374
443
|
end
|
375
444
|
|
376
|
-
def new_column(name, default,
|
377
|
-
Column.new(name, default,
|
445
|
+
def new_column(name, default, sql_type_metadata, null, table_name, default_function = nil, collation = nil) # :nodoc:
|
446
|
+
Column.new(name, default, sql_type_metadata, null, table_name, default_function, collation)
|
378
447
|
end
|
379
448
|
|
380
449
|
def lookup_cast_type(sql_type) # :nodoc:
|
@@ -385,18 +454,36 @@ module ActiveRecord
|
|
385
454
|
visitor.accept(node, collector).value
|
386
455
|
end
|
387
456
|
|
457
|
+
def combine_bind_parameters(
|
458
|
+
from_clause: [],
|
459
|
+
join_clause: [],
|
460
|
+
where_clause: [],
|
461
|
+
having_clause: [],
|
462
|
+
limit: nil,
|
463
|
+
offset: nil
|
464
|
+
) # :nodoc:
|
465
|
+
result = from_clause + join_clause + where_clause + having_clause
|
466
|
+
if limit
|
467
|
+
result << limit
|
468
|
+
end
|
469
|
+
if offset
|
470
|
+
result << offset
|
471
|
+
end
|
472
|
+
result
|
473
|
+
end
|
474
|
+
|
388
475
|
protected
|
389
476
|
|
390
477
|
def initialize_type_map(m) # :nodoc:
|
391
|
-
register_class_with_limit m, %r(boolean)i,
|
392
|
-
register_class_with_limit m, %r(char)i,
|
393
|
-
register_class_with_limit m, %r(binary)i,
|
394
|
-
register_class_with_limit m, %r(text)i,
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
register_class_with_limit m, %r(float)i,
|
399
|
-
register_class_with_limit m, %r(int)i,
|
478
|
+
register_class_with_limit m, %r(boolean)i, Type::Boolean
|
479
|
+
register_class_with_limit m, %r(char)i, Type::String
|
480
|
+
register_class_with_limit m, %r(binary)i, Type::Binary
|
481
|
+
register_class_with_limit m, %r(text)i, Type::Text
|
482
|
+
register_class_with_precision m, %r(date)i, Type::Date
|
483
|
+
register_class_with_precision m, %r(time)i, Type::Time
|
484
|
+
register_class_with_precision m, %r(datetime)i, Type::DateTime
|
485
|
+
register_class_with_limit m, %r(float)i, Type::Float
|
486
|
+
register_class_with_limit m, %r(int)i, Type::Integer
|
400
487
|
|
401
488
|
m.alias_type %r(blob)i, 'binary'
|
402
489
|
m.alias_type %r(clob)i, 'text'
|
@@ -430,6 +517,13 @@ module ActiveRecord
|
|
430
517
|
end
|
431
518
|
end
|
432
519
|
|
520
|
+
def register_class_with_precision(mapping, key, klass) # :nodoc:
|
521
|
+
mapping.register_type(key) do |*args|
|
522
|
+
precision = extract_precision(args.last)
|
523
|
+
klass.new(precision: precision)
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
433
527
|
def extract_scale(sql_type) # :nodoc:
|
434
528
|
case sql_type
|
435
529
|
when /\((\d+)\)/ then 0
|
@@ -476,7 +570,7 @@ module ActiveRecord
|
|
476
570
|
|
477
571
|
def translate_exception(exception, message)
|
478
572
|
# override in derived class
|
479
|
-
ActiveRecord::StatementInvalid.new(message
|
573
|
+
ActiveRecord::StatementInvalid.new(message)
|
480
574
|
end
|
481
575
|
|
482
576
|
def without_prepared_statement?(binds)
|