activerecord 4.2.11.3 → 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 +5 -5
- data/CHANGELOG.md +1281 -1204
- 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 +35 -24
- 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 +49 -41
- data/lib/active_record/associations/collection_proxy.rb +67 -27
- 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 +16 -10
- 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 +19 -140
- 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 +13 -37
- data/lib/active_record/attribute_methods.rb +76 -47
- 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 -81
- 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 -10
- 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 +380 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
- 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 +29 -166
- 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 -57
- 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 +149 -192
- 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 +4 -4
- 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 +363 -133
- data/lib/active_record/model_schema.rb +129 -41
- 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 +23 -16
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +69 -46
- 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 +79 -108
- 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 -16
- 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 -14
- 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 +57 -43
- data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
- 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 -45
- 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 +8 -4
- 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 +59 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- 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 -64
- 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 -110
@@ -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,17 +95,25 @@ 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
|
112
117
|
end
|
113
118
|
|
114
119
|
class Version
|
@@ -125,7 +130,8 @@ module ActiveRecord
|
|
125
130
|
|
126
131
|
class BindCollector < Arel::Collectors::Bind
|
127
132
|
def compile(bvs, conn)
|
128
|
-
|
133
|
+
casted_binds = conn.prepare_binds_for_database(bvs)
|
134
|
+
super(casted_binds.map { |value| conn.quote(value) })
|
129
135
|
end
|
130
136
|
end
|
131
137
|
|
@@ -143,20 +149,32 @@ module ActiveRecord
|
|
143
149
|
end
|
144
150
|
end
|
145
151
|
|
152
|
+
def arel_visitor # :nodoc:
|
153
|
+
Arel::Visitors::ToSql.new(self)
|
154
|
+
end
|
155
|
+
|
146
156
|
def valid_type?(type)
|
147
|
-
|
157
|
+
false
|
148
158
|
end
|
149
159
|
|
150
160
|
def schema_creation
|
151
161
|
SchemaCreation.new self
|
152
162
|
end
|
153
163
|
|
164
|
+
# this method must only be called while holding connection pool's mutex
|
154
165
|
def lease
|
155
|
-
|
156
|
-
|
157
|
-
|
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}."
|
158
173
|
end
|
174
|
+
raise ActiveRecordError, msg
|
159
175
|
end
|
176
|
+
|
177
|
+
@owner = Thread.current
|
160
178
|
end
|
161
179
|
|
162
180
|
def schema_cache=(cache)
|
@@ -164,6 +182,7 @@ module ActiveRecord
|
|
164
182
|
@schema_cache = cache
|
165
183
|
end
|
166
184
|
|
185
|
+
# this method must only be called while holding connection pool's mutex
|
167
186
|
def expire
|
168
187
|
@owner = nil
|
169
188
|
end
|
@@ -207,6 +226,11 @@ module ActiveRecord
|
|
207
226
|
false
|
208
227
|
end
|
209
228
|
|
229
|
+
# Does this adapter support application-enforced advisory locking?
|
230
|
+
def supports_advisory_locks?
|
231
|
+
false
|
232
|
+
end
|
233
|
+
|
210
234
|
# Should primary key values be selected from their corresponding
|
211
235
|
# sequence before the insert statement? If true, next_sequence_value
|
212
236
|
# is called before each insert to set the record's primary key.
|
@@ -224,6 +248,11 @@ module ActiveRecord
|
|
224
248
|
false
|
225
249
|
end
|
226
250
|
|
251
|
+
# Does this adapter support expression indices?
|
252
|
+
def supports_expression_index?
|
253
|
+
false
|
254
|
+
end
|
255
|
+
|
227
256
|
# Does this adapter support explain?
|
228
257
|
def supports_explain?
|
229
258
|
false
|
@@ -255,6 +284,31 @@ module ActiveRecord
|
|
255
284
|
false
|
256
285
|
end
|
257
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
|
+
|
258
312
|
# This is meant to be implemented by the adapters that support extensions
|
259
313
|
def disable_extension(name)
|
260
314
|
end
|
@@ -263,6 +317,20 @@ module ActiveRecord
|
|
263
317
|
def enable_extension(name)
|
264
318
|
end
|
265
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
|
+
|
266
334
|
# A list of extensions, to be filled in by adapters that support them.
|
267
335
|
def extensions
|
268
336
|
[]
|
@@ -273,14 +341,6 @@ module ActiveRecord
|
|
273
341
|
{}
|
274
342
|
end
|
275
343
|
|
276
|
-
# QUOTING ==================================================
|
277
|
-
|
278
|
-
# Returns a bind substitution value given a bind +column+
|
279
|
-
# NOTE: The column param is currently being used by the sqlserver-adapter
|
280
|
-
def substitute_at(column, _unused = 0)
|
281
|
-
Arel::Nodes::BindParam.new
|
282
|
-
end
|
283
|
-
|
284
344
|
# REFERENTIAL INTEGRITY ====================================
|
285
345
|
|
286
346
|
# Override to turn off referential integrity while executing <tt>&block</tt>.
|
@@ -334,14 +394,14 @@ module ActiveRecord
|
|
334
394
|
end
|
335
395
|
|
336
396
|
# Checks whether the connection to the database is still active (i.e. not stale).
|
337
|
-
# This is done under the hood by calling
|
397
|
+
# This is done under the hood by calling #active?. If the connection
|
338
398
|
# is no longer active, then this method will reconnect to the database.
|
339
399
|
def verify!(*ignored)
|
340
400
|
reconnect! unless active?
|
341
401
|
end
|
342
402
|
|
343
403
|
# Provides access to the underlying database driver for this adapter. For
|
344
|
-
# example, this method returns a
|
404
|
+
# example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
|
345
405
|
# and a PGconn object in case of PostgreSQLAdapter.
|
346
406
|
#
|
347
407
|
# This is useful for when you need to call a proprietary method such as
|
@@ -350,29 +410,26 @@ module ActiveRecord
|
|
350
410
|
@connection
|
351
411
|
end
|
352
412
|
|
353
|
-
def create_savepoint(name = nil)
|
354
|
-
end
|
355
|
-
|
356
|
-
def release_savepoint(name = nil)
|
357
|
-
end
|
358
|
-
|
359
|
-
def case_sensitive_modifier(node, table_attribute)
|
360
|
-
node
|
361
|
-
end
|
362
|
-
|
363
413
|
def case_sensitive_comparison(table, attribute, column, value)
|
364
|
-
|
365
|
-
|
366
|
-
|
414
|
+
if value.nil?
|
415
|
+
table[attribute].eq(value)
|
416
|
+
else
|
417
|
+
table[attribute].eq(Arel::Nodes::BindParam.new)
|
418
|
+
end
|
367
419
|
end
|
368
420
|
|
369
421
|
def case_insensitive_comparison(table, attribute, column, value)
|
370
|
-
|
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
|
371
427
|
end
|
372
428
|
|
373
|
-
def
|
374
|
-
|
429
|
+
def can_perform_case_insensitive_comparison_for?(column)
|
430
|
+
true
|
375
431
|
end
|
432
|
+
private :can_perform_case_insensitive_comparison_for?
|
376
433
|
|
377
434
|
# Check the connection back in to the connection pool
|
378
435
|
def close
|
@@ -385,8 +442,8 @@ module ActiveRecord
|
|
385
442
|
end
|
386
443
|
end
|
387
444
|
|
388
|
-
def new_column(name, default,
|
389
|
-
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)
|
390
447
|
end
|
391
448
|
|
392
449
|
def lookup_cast_type(sql_type) # :nodoc:
|
@@ -397,18 +454,36 @@ module ActiveRecord
|
|
397
454
|
visitor.accept(node, collector).value
|
398
455
|
end
|
399
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
|
+
|
400
475
|
protected
|
401
476
|
|
402
477
|
def initialize_type_map(m) # :nodoc:
|
403
|
-
register_class_with_limit m, %r(boolean)i,
|
404
|
-
register_class_with_limit m, %r(char)i,
|
405
|
-
register_class_with_limit m, %r(binary)i,
|
406
|
-
register_class_with_limit m, %r(text)i,
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
register_class_with_limit m, %r(float)i,
|
411
|
-
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
|
412
487
|
|
413
488
|
m.alias_type %r(blob)i, 'binary'
|
414
489
|
m.alias_type %r(clob)i, 'text'
|
@@ -442,6 +517,13 @@ module ActiveRecord
|
|
442
517
|
end
|
443
518
|
end
|
444
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
|
+
|
445
527
|
def extract_scale(sql_type) # :nodoc:
|
446
528
|
case sql_type
|
447
529
|
when /\((\d+)\)/ then 0
|
@@ -488,7 +570,7 @@ module ActiveRecord
|
|
488
570
|
|
489
571
|
def translate_exception(exception, message)
|
490
572
|
# override in derived class
|
491
|
-
ActiveRecord::StatementInvalid.new(message
|
573
|
+
ActiveRecord::StatementInvalid.new(message)
|
492
574
|
end
|
493
575
|
|
494
576
|
def without_prepared_statement?(binds)
|