activerecord 5.1.7 → 5.2.0.beta1
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 +221 -900
- data/README.rdoc +3 -3
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +10 -3
- data/lib/active_record/aggregations.rb +2 -0
- data/lib/active_record/association_relation.rb +2 -0
- data/lib/active_record/associations.rb +13 -42
- data/lib/active_record/associations/alias_tracker.rb +17 -17
- data/lib/active_record/associations/association.rb +11 -22
- data/lib/active_record/associations/association_scope.rb +32 -44
- data/lib/active_record/associations/belongs_to_association.rb +6 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
- data/lib/active_record/associations/builder/association.rb +2 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -12
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +41 -33
- data/lib/active_record/associations/collection_proxy.rb +11 -14
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +4 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/has_one_through_association.rb +3 -1
- data/lib/active_record/associations/join_dependency.rb +22 -40
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +42 -58
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +2 -0
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +47 -7
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +25 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +8 -2
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +5 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +6 -8
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +120 -28
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -6
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +47 -82
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +19 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +27 -57
- data/lib/active_record/counter_cache.rb +15 -12
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +15 -13
- data/lib/active_record/errors.rb +54 -21
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +40 -24
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +6 -5
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +31 -20
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +2 -0
- data/lib/active_record/migration.rb +47 -21
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +20 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +29 -38
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +184 -40
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +54 -1
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +41 -28
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +100 -182
- data/lib/active_record/relation.rb +61 -193
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +40 -23
- data/lib/active_record/relation/delegation.rb +10 -27
- data/lib/active_record/relation/finder_methods.rb +53 -49
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +22 -19
- data/lib/active_record/relation/predicate_builder.rb +42 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +80 -69
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -0
- data/lib/active_record/relation/where_clause.rb +50 -67
- data/lib/active_record/relation/where_clause_factory.rb +4 -46
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +15 -9
- data/lib/active_record/schema.rb +3 -1
- data/lib/active_record/schema_dumper.rb +24 -23
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +15 -7
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +2 -0
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +3 -1
- data/lib/active_record/tasks/database_tasks.rb +23 -12
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -4
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +2 -0
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +25 -38
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,10 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
class TransactionState
|
4
|
-
VALID_STATES = Set.new([:committed, :rolledback, nil])
|
5
|
-
|
6
6
|
def initialize(state = nil)
|
7
7
|
@state = state
|
8
|
+
@children = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_child(state)
|
12
|
+
@children << state
|
8
13
|
end
|
9
14
|
|
10
15
|
def finalized?
|
@@ -19,15 +24,43 @@ module ActiveRecord
|
|
19
24
|
@state == :rolledback
|
20
25
|
end
|
21
26
|
|
27
|
+
def fully_completed?
|
28
|
+
completed?
|
29
|
+
end
|
30
|
+
|
22
31
|
def completed?
|
23
32
|
committed? || rolledback?
|
24
33
|
end
|
25
34
|
|
26
35
|
def set_state(state)
|
27
|
-
|
36
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
37
|
+
The set_state method is deprecated and will be removed in
|
38
|
+
Rails 6.0. Please use rollback! or commit! to set transaction
|
39
|
+
state directly.
|
40
|
+
MSG
|
41
|
+
case state
|
42
|
+
when :rolledback
|
43
|
+
rollback!
|
44
|
+
when :committed
|
45
|
+
commit!
|
46
|
+
when nil
|
47
|
+
nullify!
|
48
|
+
else
|
28
49
|
raise ArgumentError, "Invalid transaction state: #{state}"
|
29
50
|
end
|
30
|
-
|
51
|
+
end
|
52
|
+
|
53
|
+
def rollback!
|
54
|
+
@children.each { |c| c.rollback! }
|
55
|
+
@state = :rolledback
|
56
|
+
end
|
57
|
+
|
58
|
+
def commit!
|
59
|
+
@state = :committed
|
60
|
+
end
|
61
|
+
|
62
|
+
def nullify!
|
63
|
+
@state = nil
|
31
64
|
end
|
32
65
|
end
|
33
66
|
|
@@ -57,7 +90,7 @@ module ActiveRecord
|
|
57
90
|
end
|
58
91
|
|
59
92
|
def rollback
|
60
|
-
@state.
|
93
|
+
@state.rollback!
|
61
94
|
end
|
62
95
|
|
63
96
|
def rollback_records
|
@@ -72,7 +105,7 @@ module ActiveRecord
|
|
72
105
|
end
|
73
106
|
|
74
107
|
def commit
|
75
|
-
@state.
|
108
|
+
@state.commit!
|
76
109
|
end
|
77
110
|
|
78
111
|
def before_commit_records
|
@@ -100,8 +133,11 @@ module ActiveRecord
|
|
100
133
|
end
|
101
134
|
|
102
135
|
class SavepointTransaction < Transaction
|
103
|
-
def initialize(connection, savepoint_name, options, *args)
|
136
|
+
def initialize(connection, savepoint_name, parent_transaction, options, *args)
|
104
137
|
super(connection, options, *args)
|
138
|
+
|
139
|
+
parent_transaction.state.add_child(@state)
|
140
|
+
|
105
141
|
if options[:isolation]
|
106
142
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
107
143
|
end
|
@@ -155,7 +191,7 @@ module ActiveRecord
|
|
155
191
|
if @stack.empty?
|
156
192
|
RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
|
157
193
|
else
|
158
|
-
SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options,
|
194
|
+
SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options,
|
159
195
|
run_commit_callbacks: run_commit_callbacks)
|
160
196
|
end
|
161
197
|
|
@@ -204,7 +240,7 @@ module ActiveRecord
|
|
204
240
|
rollback_transaction if transaction
|
205
241
|
else
|
206
242
|
begin
|
207
|
-
commit_transaction
|
243
|
+
commit_transaction if transaction
|
208
244
|
rescue Exception
|
209
245
|
rollback_transaction(transaction) unless transaction.state.completed?
|
210
246
|
raise
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "active_record/connection_adapters/determine_if_preparable_visitor"
|
3
4
|
require "active_record/connection_adapters/schema_cache"
|
4
5
|
require "active_record/connection_adapters/sql_type_metadata"
|
@@ -6,7 +7,9 @@ require "active_record/connection_adapters/abstract/schema_dumper"
|
|
6
7
|
require "active_record/connection_adapters/abstract/schema_creation"
|
7
8
|
require "active_support/concurrency/load_interlock_aware_monitor"
|
8
9
|
require "arel/collectors/bind"
|
10
|
+
require "arel/collectors/composite"
|
9
11
|
require "arel/collectors/sql_string"
|
12
|
+
require "arel/collectors/substitute_binds"
|
10
13
|
|
11
14
|
module ActiveRecord
|
12
15
|
module ConnectionAdapters # :nodoc:
|
@@ -69,7 +72,6 @@ module ActiveRecord
|
|
69
72
|
include Quoting, DatabaseStatements, SchemaStatements
|
70
73
|
include DatabaseLimits
|
71
74
|
include QueryCache
|
72
|
-
include ColumnDumper
|
73
75
|
include Savepoints
|
74
76
|
|
75
77
|
SIMPLE_INT = /\A\d+\z/
|
@@ -103,6 +105,7 @@ module ActiveRecord
|
|
103
105
|
@logger = logger
|
104
106
|
@config = config
|
105
107
|
@pool = nil
|
108
|
+
@idle_since = Concurrent.monotonic_time
|
106
109
|
@schema_cache = SchemaCache.new self
|
107
110
|
@quoted_column_names, @quoted_table_names = {}, {}
|
108
111
|
@visitor = arel_visitor
|
@@ -128,51 +131,14 @@ module ActiveRecord
|
|
128
131
|
end
|
129
132
|
end
|
130
133
|
|
131
|
-
class BindCollector < Arel::Collectors::Bind
|
132
|
-
def compile(bvs, conn)
|
133
|
-
casted_binds = bvs.map(&:value_for_database)
|
134
|
-
super(casted_binds.map { |value| conn.quote(value) })
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
class SQLString < Arel::Collectors::SQLString
|
139
|
-
def compile(bvs, conn)
|
140
|
-
super(bvs)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def collector
|
145
|
-
if prepared_statements
|
146
|
-
SQLString.new
|
147
|
-
else
|
148
|
-
BindCollector.new
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def arel_visitor # :nodoc:
|
153
|
-
Arel::Visitors::ToSql.new(self)
|
154
|
-
end
|
155
|
-
|
156
134
|
def valid_type?(type) # :nodoc:
|
157
135
|
!native_database_types[type].nil?
|
158
136
|
end
|
159
137
|
|
160
|
-
def schema_creation
|
161
|
-
SchemaCreation.new self
|
162
|
-
end
|
163
|
-
|
164
|
-
# Returns an array of +Column+ objects for the table specified by +table_name+.
|
165
|
-
def columns(table_name) # :nodoc:
|
166
|
-
table_name = table_name.to_s
|
167
|
-
column_definitions(table_name).map do |field|
|
168
|
-
new_column_from_field(table_name, field)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
138
|
# this method must only be called while holding connection pool's mutex
|
173
139
|
def lease
|
174
140
|
if in_use?
|
175
|
-
msg = "Cannot lease connection, "
|
141
|
+
msg = "Cannot lease connection, ".dup
|
176
142
|
if @owner == Thread.current
|
177
143
|
msg << "it is already leased by the current thread."
|
178
144
|
else
|
@@ -199,6 +165,7 @@ module ActiveRecord
|
|
199
165
|
"Current thread: #{Thread.current}."
|
200
166
|
end
|
201
167
|
|
168
|
+
@idle_since = Concurrent.monotonic_time
|
202
169
|
@owner = nil
|
203
170
|
else
|
204
171
|
raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
|
@@ -218,6 +185,12 @@ module ActiveRecord
|
|
218
185
|
end
|
219
186
|
end
|
220
187
|
|
188
|
+
# Seconds since this connection was returned to the pool
|
189
|
+
def seconds_idle # :nodoc:
|
190
|
+
return 0 if in_use?
|
191
|
+
Concurrent.monotonic_time - @idle_since
|
192
|
+
end
|
193
|
+
|
221
194
|
def unprepared_statement
|
222
195
|
old_prepared_statements, @prepared_statements = @prepared_statements, false
|
223
196
|
yield
|
@@ -231,16 +204,6 @@ module ActiveRecord
|
|
231
204
|
self.class::ADAPTER_NAME
|
232
205
|
end
|
233
206
|
|
234
|
-
def supports_migrations? # :nodoc:
|
235
|
-
true
|
236
|
-
end
|
237
|
-
deprecate :supports_migrations?
|
238
|
-
|
239
|
-
def supports_primary_key? # :nodoc:
|
240
|
-
true
|
241
|
-
end
|
242
|
-
deprecate :supports_primary_key?
|
243
|
-
|
244
207
|
# Does this adapter support DDL rollbacks in transactions? That is, would
|
245
208
|
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
246
209
|
def supports_ddl_transactions?
|
@@ -412,6 +375,19 @@ module ActiveRecord
|
|
412
375
|
reset_transaction
|
413
376
|
end
|
414
377
|
|
378
|
+
# Immediately forget this connection ever existed. Unlike disconnect!,
|
379
|
+
# this will not communicate with the server.
|
380
|
+
#
|
381
|
+
# After calling this method, the behavior of all other methods becomes
|
382
|
+
# undefined. This is called internally just before a forked process gets
|
383
|
+
# rid of a connection that belonged to its parent.
|
384
|
+
def discard!
|
385
|
+
# This should be overridden by concrete adapters.
|
386
|
+
#
|
387
|
+
# Prevent @connection's finalizer from touching the socket, or
|
388
|
+
# otherwise communicating with its server, when it is collected.
|
389
|
+
end
|
390
|
+
|
415
391
|
# Reset the state of this connection, directing the DBMS to clear
|
416
392
|
# transactions and other connection-related server-side state. Usually a
|
417
393
|
# database-dependent operation.
|
@@ -437,10 +413,7 @@ module ActiveRecord
|
|
437
413
|
# Checks whether the connection to the database is still active (i.e. not stale).
|
438
414
|
# This is done under the hood by calling #active?. If the connection
|
439
415
|
# is no longer active, then this method will reconnect to the database.
|
440
|
-
def verify!
|
441
|
-
if ignored.size > 0
|
442
|
-
ActiveSupport::Deprecation.warn("Passing arguments to #verify method of the connection has no effect and has been deprecated. Please remove all arguments from the #verify method call.")
|
443
|
-
end
|
416
|
+
def verify!
|
444
417
|
reconnect! unless active?
|
445
418
|
end
|
446
419
|
|
@@ -476,40 +449,12 @@ module ActiveRecord
|
|
476
449
|
pool.checkin self
|
477
450
|
end
|
478
451
|
|
479
|
-
def
|
480
|
-
|
481
|
-
initialize_type_map(mapping)
|
482
|
-
end
|
483
|
-
end
|
484
|
-
|
485
|
-
def new_column(name, default, sql_type_metadata, null, table_name, default_function = nil, collation = nil) # :nodoc:
|
486
|
-
Column.new(name, default, sql_type_metadata, null, table_name, default_function, collation)
|
487
|
-
end
|
488
|
-
|
489
|
-
def lookup_cast_type(sql_type) # :nodoc:
|
490
|
-
type_map.lookup(sql_type)
|
452
|
+
def column_name_for_operation(operation, node) # :nodoc:
|
453
|
+
column_name_from_arel_node(node)
|
491
454
|
end
|
492
455
|
|
493
|
-
def
|
494
|
-
visitor.accept(node,
|
495
|
-
end
|
496
|
-
|
497
|
-
def combine_bind_parameters(
|
498
|
-
from_clause: [],
|
499
|
-
join_clause: [],
|
500
|
-
where_clause: [],
|
501
|
-
having_clause: [],
|
502
|
-
limit: nil,
|
503
|
-
offset: nil
|
504
|
-
) # :nodoc:
|
505
|
-
result = from_clause + join_clause + where_clause + having_clause
|
506
|
-
if limit
|
507
|
-
result << limit
|
508
|
-
end
|
509
|
-
if offset
|
510
|
-
result << offset
|
511
|
-
end
|
512
|
-
result
|
456
|
+
def column_name_from_arel_node(node) # :nodoc:
|
457
|
+
visitor.accept(node, Arel::Collectors::SQLString.new).value
|
513
458
|
end
|
514
459
|
|
515
460
|
def default_index_type?(index) # :nodoc:
|
@@ -517,8 +462,13 @@ module ActiveRecord
|
|
517
462
|
end
|
518
463
|
|
519
464
|
private
|
465
|
+
def type_map
|
466
|
+
@type_map ||= Type::TypeMap.new.tap do |mapping|
|
467
|
+
initialize_type_map(mapping)
|
468
|
+
end
|
469
|
+
end
|
520
470
|
|
521
|
-
def initialize_type_map(m)
|
471
|
+
def initialize_type_map(m = type_map)
|
522
472
|
register_class_with_limit m, %r(boolean)i, Type::Boolean
|
523
473
|
register_class_with_limit m, %r(char)i, Type::String
|
524
474
|
register_class_with_limit m, %r(binary)i, Type::Binary
|
@@ -536,6 +486,8 @@ module ActiveRecord
|
|
536
486
|
m.alias_type %r(number)i, "decimal"
|
537
487
|
m.alias_type %r(double)i, "float"
|
538
488
|
|
489
|
+
m.register_type %r(^json)i, Type::Json.new
|
490
|
+
|
539
491
|
m.register_type(%r(decimal)i) do |sql_type|
|
540
492
|
scale = extract_scale(sql_type)
|
541
493
|
precision = extract_precision(sql_type)
|
@@ -551,7 +503,7 @@ module ActiveRecord
|
|
551
503
|
|
552
504
|
def reload_type_map
|
553
505
|
type_map.clear
|
554
|
-
initialize_type_map
|
506
|
+
initialize_type_map
|
555
507
|
end
|
556
508
|
|
557
509
|
def register_class_with_limit(mapping, key, klass)
|
@@ -609,12 +561,14 @@ module ActiveRecord
|
|
609
561
|
type_casted_binds: type_casted_binds,
|
610
562
|
statement_name: statement_name,
|
611
563
|
connection_id: object_id) do
|
564
|
+
begin
|
612
565
|
@lock.synchronize do
|
613
566
|
yield
|
614
567
|
end
|
568
|
+
rescue => e
|
569
|
+
raise translate_exception_class(e, sql)
|
615
570
|
end
|
616
|
-
|
617
|
-
raise translate_exception_class(e, sql)
|
571
|
+
end
|
618
572
|
end
|
619
573
|
|
620
574
|
def translate_exception(exception, message)
|
@@ -636,6 +590,24 @@ module ActiveRecord
|
|
636
590
|
columns(table_name).detect { |c| c.name == column_name } ||
|
637
591
|
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
638
592
|
end
|
593
|
+
|
594
|
+
def collector
|
595
|
+
if prepared_statements
|
596
|
+
Arel::Collectors::Composite.new(
|
597
|
+
Arel::Collectors::SQLString.new,
|
598
|
+
Arel::Collectors::Bind.new,
|
599
|
+
)
|
600
|
+
else
|
601
|
+
Arel::Collectors::SubstituteBinds.new(
|
602
|
+
self,
|
603
|
+
Arel::Collectors::SQLString.new,
|
604
|
+
)
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
def arel_visitor
|
609
|
+
Arel::Visitors::ToSql.new(self)
|
610
|
+
end
|
639
611
|
end
|
640
612
|
end
|
641
613
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record/connection_adapters/abstract_adapter"
|
2
4
|
require "active_record/connection_adapters/statement_pool"
|
3
5
|
require "active_record/connection_adapters/mysql/column"
|
@@ -15,21 +17,8 @@ module ActiveRecord
|
|
15
17
|
module ConnectionAdapters
|
16
18
|
class AbstractMysqlAdapter < AbstractAdapter
|
17
19
|
include MySQL::Quoting
|
18
|
-
include MySQL::ColumnDumper
|
19
20
|
include MySQL::SchemaStatements
|
20
21
|
|
21
|
-
def update_table_definition(table_name, base) # :nodoc:
|
22
|
-
MySQL::Table.new(table_name, base)
|
23
|
-
end
|
24
|
-
|
25
|
-
def schema_creation # :nodoc:
|
26
|
-
MySQL::SchemaCreation.new(self)
|
27
|
-
end
|
28
|
-
|
29
|
-
def arel_visitor # :nodoc:
|
30
|
-
Arel::Visitors::MySQL.new(self)
|
31
|
-
end
|
32
|
-
|
33
22
|
##
|
34
23
|
# :singleton-method:
|
35
24
|
# By default, the Mysql2Adapter will consider all columns of type <tt>tinyint(1)</tt>
|
@@ -37,15 +26,14 @@ module ActiveRecord
|
|
37
26
|
# to your application.rb file:
|
38
27
|
#
|
39
28
|
# ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
|
40
|
-
class_attribute :emulate_booleans
|
41
|
-
self.emulate_booleans = true
|
29
|
+
class_attribute :emulate_booleans, default: true
|
42
30
|
|
43
31
|
NATIVE_DATABASE_TYPES = {
|
44
32
|
primary_key: "bigint auto_increment PRIMARY KEY",
|
45
33
|
string: { name: "varchar", limit: 255 },
|
46
34
|
text: { name: "text", limit: 65535 },
|
47
35
|
integer: { name: "int", limit: 4 },
|
48
|
-
float: { name: "float" },
|
36
|
+
float: { name: "float", limit: 24 },
|
49
37
|
decimal: { name: "decimal" },
|
50
38
|
datetime: { name: "datetime" },
|
51
39
|
timestamp: { name: "timestamp" },
|
@@ -56,10 +44,7 @@ module ActiveRecord
|
|
56
44
|
json: { name: "json" },
|
57
45
|
}
|
58
46
|
|
59
|
-
|
60
|
-
INDEX_USINGS = [:btree, :hash]
|
61
|
-
|
62
|
-
class StatementPool < ConnectionAdapters::StatementPool
|
47
|
+
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
|
63
48
|
private def dealloc(stmt)
|
64
49
|
stmt[:stmt].close
|
65
50
|
end
|
@@ -87,16 +72,8 @@ module ActiveRecord
|
|
87
72
|
true
|
88
73
|
end
|
89
74
|
|
90
|
-
# Returns true, since this connection adapter supports prepared statement
|
91
|
-
# caching.
|
92
|
-
def supports_statement_cache?
|
93
|
-
true
|
94
|
-
end
|
95
|
-
|
96
|
-
# Technically MySQL allows to create indexes with the sort order syntax
|
97
|
-
# but at the moment (5.5) it doesn't yet implement them
|
98
75
|
def supports_index_sort_order?
|
99
|
-
|
76
|
+
!mariadb? && version >= "8.0.1"
|
100
77
|
end
|
101
78
|
|
102
79
|
def supports_transaction_isolation?
|
@@ -140,11 +117,11 @@ module ActiveRecord
|
|
140
117
|
end
|
141
118
|
|
142
119
|
def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
|
143
|
-
query_value("SELECT GET_LOCK(#{quote(lock_name
|
120
|
+
query_value("SELECT GET_LOCK(#{quote(lock_name)}, #{timeout})") == 1
|
144
121
|
end
|
145
122
|
|
146
123
|
def release_advisory_lock(lock_name) # :nodoc:
|
147
|
-
query_value("SELECT RELEASE_LOCK(#{quote(lock_name
|
124
|
+
query_value("SELECT RELEASE_LOCK(#{quote(lock_name)})") == 1
|
148
125
|
end
|
149
126
|
|
150
127
|
def native_database_types
|
@@ -152,7 +129,7 @@ module ActiveRecord
|
|
152
129
|
end
|
153
130
|
|
154
131
|
def index_algorithms
|
155
|
-
{ default: "ALGORITHM = DEFAULT", copy: "ALGORITHM = COPY", inplace: "ALGORITHM = INPLACE" }
|
132
|
+
{ default: "ALGORITHM = DEFAULT".dup, copy: "ALGORITHM = COPY".dup, inplace: "ALGORITHM = INPLACE".dup }
|
156
133
|
end
|
157
134
|
|
158
135
|
# HELPER METHODS ===========================================
|
@@ -163,10 +140,6 @@ module ActiveRecord
|
|
163
140
|
raise NotImplementedError
|
164
141
|
end
|
165
142
|
|
166
|
-
def new_column(*args) #:nodoc:
|
167
|
-
MySQL::Column.new(*args)
|
168
|
-
end
|
169
|
-
|
170
143
|
# Must return the MySQL error number from the exception, if the exception has an
|
171
144
|
# error number.
|
172
145
|
def error_number(exception) # :nodoc:
|
@@ -308,50 +281,10 @@ module ActiveRecord
|
|
308
281
|
execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
|
309
282
|
end
|
310
283
|
|
311
|
-
# Returns an array of indexes for the given table.
|
312
|
-
def indexes(table_name, name = nil) #:nodoc:
|
313
|
-
if name
|
314
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
315
|
-
Passing name to #indexes is deprecated without replacement.
|
316
|
-
MSG
|
317
|
-
end
|
318
|
-
|
319
|
-
indexes = []
|
320
|
-
current_index = nil
|
321
|
-
execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", "SCHEMA") do |result|
|
322
|
-
each_hash(result) do |row|
|
323
|
-
if current_index != row[:Key_name]
|
324
|
-
next if row[:Key_name] == "PRIMARY" # skip the primary key
|
325
|
-
current_index = row[:Key_name]
|
326
|
-
|
327
|
-
mysql_index_type = row[:Index_type].downcase.to_sym
|
328
|
-
index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
|
329
|
-
index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
|
330
|
-
indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], {}, nil, nil, index_type, index_using, row[:Index_comment].presence)
|
331
|
-
end
|
332
|
-
|
333
|
-
indexes.last.columns << row[:Column_name]
|
334
|
-
indexes.last.lengths.merge!(row[:Column_name] => row[:Sub_part].to_i) if row[:Sub_part]
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
indexes
|
339
|
-
end
|
340
|
-
|
341
|
-
def new_column_from_field(table_name, field) # :nodoc:
|
342
|
-
type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
|
343
|
-
if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\(\))?\z/i.match?(field[:Default])
|
344
|
-
default, default_function = nil, "CURRENT_TIMESTAMP"
|
345
|
-
else
|
346
|
-
default, default_function = field[:Default], nil
|
347
|
-
end
|
348
|
-
new_column(field[:Field], default, type_metadata, field[:Null] == "YES", table_name, default_function, field[:Collation], comment: field[:Comment].presence)
|
349
|
-
end
|
350
|
-
|
351
284
|
def table_comment(table_name) # :nodoc:
|
352
285
|
scope = quoted_scope(table_name)
|
353
286
|
|
354
|
-
query_value(<<-SQL.strip_heredoc, "SCHEMA")
|
287
|
+
query_value(<<-SQL.strip_heredoc, "SCHEMA").presence
|
355
288
|
SELECT table_comment
|
356
289
|
FROM information_schema.tables
|
357
290
|
WHERE table_schema = #{scope[:schema]}
|
@@ -378,6 +311,11 @@ module ActiveRecord
|
|
378
311
|
execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}")
|
379
312
|
end
|
380
313
|
|
314
|
+
def change_table_comment(table_name, comment) #:nodoc:
|
315
|
+
comment = "" if comment.nil?
|
316
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} COMMENT #{quote(comment)}")
|
317
|
+
end
|
318
|
+
|
381
319
|
# Renames a table.
|
382
320
|
#
|
383
321
|
# Example:
|
@@ -418,18 +356,19 @@ module ActiveRecord
|
|
418
356
|
|
419
357
|
def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
|
420
358
|
default = extract_new_default_value(default_or_changes)
|
421
|
-
|
422
|
-
change_column table_name, column_name, column.sql_type, default: default
|
359
|
+
change_column table_name, column_name, nil, default: default
|
423
360
|
end
|
424
361
|
|
425
362
|
def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
|
426
|
-
column = column_for(table_name, column_name)
|
427
|
-
|
428
363
|
unless null || default.nil?
|
429
364
|
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
430
365
|
end
|
431
366
|
|
432
|
-
change_column table_name, column_name,
|
367
|
+
change_column table_name, column_name, nil, null: null
|
368
|
+
end
|
369
|
+
|
370
|
+
def change_column_comment(table_name, column_name, comment) #:nodoc:
|
371
|
+
change_column table_name, column_name, nil, comment: comment
|
433
372
|
end
|
434
373
|
|
435
374
|
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
@@ -443,7 +382,7 @@ module ActiveRecord
|
|
443
382
|
|
444
383
|
def add_index(table_name, column_name, options = {}) #:nodoc:
|
445
384
|
index_name, index_type, index_columns, _, index_algorithm, index_using, comment = add_index_options(table_name, column_name, options)
|
446
|
-
sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} ON #{quote_table_name(table_name)} (#{index_columns}) #{index_algorithm}"
|
385
|
+
sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} ON #{quote_table_name(table_name)} (#{index_columns}) #{index_algorithm}".dup
|
447
386
|
execute add_sql_comment!(sql, comment)
|
448
387
|
end
|
449
388
|
|
@@ -464,13 +403,12 @@ module ActiveRecord
|
|
464
403
|
fk.constraint_name AS 'name',
|
465
404
|
rc.update_rule AS 'on_update',
|
466
405
|
rc.delete_rule AS 'on_delete'
|
467
|
-
FROM information_schema.
|
468
|
-
JOIN information_schema.
|
406
|
+
FROM information_schema.key_column_usage fk
|
407
|
+
JOIN information_schema.referential_constraints rc
|
469
408
|
USING (constraint_schema, constraint_name)
|
470
409
|
WHERE fk.referenced_column_name IS NOT NULL
|
471
410
|
AND fk.table_schema = #{scope[:schema]}
|
472
411
|
AND fk.table_name = #{scope[:name]}
|
473
|
-
AND rc.constraint_schema = #{scope[:schema]}
|
474
412
|
AND rc.table_name = #{scope[:name]}
|
475
413
|
SQL
|
476
414
|
|
@@ -529,7 +467,7 @@ module ActiveRecord
|
|
529
467
|
super
|
530
468
|
end
|
531
469
|
|
532
|
-
sql
|
470
|
+
sql = "#{sql} unsigned" if unsigned && type != :primary_key
|
533
471
|
sql
|
534
472
|
end
|
535
473
|
|
@@ -591,9 +529,26 @@ module ActiveRecord
|
|
591
529
|
index.using == :btree || super
|
592
530
|
end
|
593
531
|
|
532
|
+
def insert_fixtures(*)
|
533
|
+
without_sql_mode("NO_AUTO_VALUE_ON_ZERO") { super }
|
534
|
+
end
|
535
|
+
|
594
536
|
private
|
595
537
|
|
596
|
-
def
|
538
|
+
def without_sql_mode(mode)
|
539
|
+
result = execute("SELECT @@SESSION.sql_mode")
|
540
|
+
current_mode = result.first[0]
|
541
|
+
return yield unless current_mode.include?(mode)
|
542
|
+
|
543
|
+
sql_mode = "REPLACE(@@sql_mode, '#{mode}', '')"
|
544
|
+
execute("SET @@SESSION.sql_mode = #{sql_mode}")
|
545
|
+
yield
|
546
|
+
ensure
|
547
|
+
sql_mode = "CONCAT(@@sql_mode, ',#{mode}')"
|
548
|
+
execute("SET @@SESSION.sql_mode = #{sql_mode}")
|
549
|
+
end
|
550
|
+
|
551
|
+
def initialize_type_map(m = type_map)
|
597
552
|
super
|
598
553
|
|
599
554
|
register_class_with_limit m, %r(char)i, MysqlString
|
@@ -608,7 +563,6 @@ module ActiveRecord
|
|
608
563
|
m.register_type %r(longblob)i, Type::Binary.new(limit: 2**32 - 1)
|
609
564
|
m.register_type %r(^float)i, Type::Float.new(limit: 24)
|
610
565
|
m.register_type %r(^double)i, Type::Float.new(limit: 53)
|
611
|
-
m.register_type %r(^json)i, MysqlJson.new
|
612
566
|
|
613
567
|
register_integer_type m, %r(^bigint)i, limit: 8
|
614
568
|
register_integer_type m, %r(^int)i, limit: 4
|
@@ -651,10 +605,6 @@ module ActiveRecord
|
|
651
605
|
end
|
652
606
|
end
|
653
607
|
|
654
|
-
def fetch_type_metadata(sql_type, extra = "")
|
655
|
-
MySQL::TypeMetadata.new(super(sql_type), extra: extra)
|
656
|
-
end
|
657
|
-
|
658
608
|
def add_index_length(quoted_columns, **options)
|
659
609
|
if length = options[:length]
|
660
610
|
case length
|
@@ -684,6 +634,9 @@ module ActiveRecord
|
|
684
634
|
ER_LOCK_DEADLOCK = 1213
|
685
635
|
ER_CANNOT_ADD_FOREIGN = 1215
|
686
636
|
ER_CANNOT_CREATE_TABLE = 1005
|
637
|
+
ER_LOCK_WAIT_TIMEOUT = 1205
|
638
|
+
ER_QUERY_INTERRUPTED = 1317
|
639
|
+
ER_QUERY_TIMEOUT = 3024
|
687
640
|
|
688
641
|
def translate_exception(exception, message)
|
689
642
|
case error_number(exception)
|
@@ -707,6 +660,12 @@ module ActiveRecord
|
|
707
660
|
NotNullViolation.new(message)
|
708
661
|
when ER_LOCK_DEADLOCK
|
709
662
|
Deadlocked.new(message)
|
663
|
+
when ER_LOCK_WAIT_TIMEOUT
|
664
|
+
LockWaitTimeout.new(message)
|
665
|
+
when ER_QUERY_TIMEOUT
|
666
|
+
StatementTimeout.new(message)
|
667
|
+
when ER_QUERY_INTERRUPTED
|
668
|
+
QueryCanceled.new(message)
|
710
669
|
else
|
711
670
|
super
|
712
671
|
end
|
@@ -720,6 +679,7 @@ module ActiveRecord
|
|
720
679
|
|
721
680
|
def change_column_sql(table_name, column_name, type, options = {})
|
722
681
|
column = column_for(table_name, column_name)
|
682
|
+
type ||= column.sql_type
|
723
683
|
|
724
684
|
unless options.key?(:default)
|
725
685
|
options[:default] = column.default
|
@@ -768,7 +728,7 @@ module ActiveRecord
|
|
768
728
|
|
769
729
|
def remove_index_sql(table_name, options = {})
|
770
730
|
index_name = index_name_for_remove(table_name, options)
|
771
|
-
"DROP INDEX #{index_name}"
|
731
|
+
"DROP INDEX #{quote_column_name(index_name)}"
|
772
732
|
end
|
773
733
|
|
774
734
|
def add_timestamps_sql(table_name, options = {})
|
@@ -782,16 +742,14 @@ module ActiveRecord
|
|
782
742
|
# MySQL is too stupid to create a temporary table for use subquery, so we have
|
783
743
|
# to give it some prompting in the form of a subsubquery. Ugh!
|
784
744
|
def subquery_for(key, select)
|
785
|
-
|
786
|
-
|
745
|
+
subselect = select.clone
|
746
|
+
subselect.projections = [key]
|
787
747
|
|
788
748
|
# Materialize subquery by adding distinct
|
789
749
|
# to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
|
790
|
-
|
750
|
+
subselect.distinct unless select.limit || select.offset || select.orders.any?
|
791
751
|
|
792
|
-
|
793
|
-
subselect.project Arel.sql(key.name)
|
794
|
-
subselect.from subsubselect.as("__active_record_temp")
|
752
|
+
Arel::SelectManager.new(subselect.as("__active_record_temp")).project(Arel.sql(key.name))
|
795
753
|
end
|
796
754
|
|
797
755
|
def supports_rename_index?
|
@@ -812,7 +770,7 @@ module ActiveRecord
|
|
812
770
|
defaults = [":default", :default].to_set
|
813
771
|
|
814
772
|
# Make MySQL reject illegal values rather than truncating or blanking them, see
|
815
|
-
#
|
773
|
+
# https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_strict_all_tables
|
816
774
|
# If the user has provided another value for sql_mode, don't replace it.
|
817
775
|
if sql_mode = variables.delete("sql_mode")
|
818
776
|
sql_mode = quote(sql_mode)
|
@@ -829,10 +787,10 @@ module ActiveRecord
|
|
829
787
|
sql_mode_assignment = "@@SESSION.sql_mode = #{sql_mode}, " if sql_mode
|
830
788
|
|
831
789
|
# NAMES does not have an equals sign, see
|
832
|
-
#
|
790
|
+
# https://dev.mysql.com/doc/refman/5.7/en/set-names.html
|
833
791
|
# (trailing comma because variable_assignments will always have content)
|
834
792
|
if @config[:encoding]
|
835
|
-
encoding = "NAMES #{@config[:encoding]}"
|
793
|
+
encoding = "NAMES #{@config[:encoding]}".dup
|
836
794
|
encoding << " COLLATE #{@config[:collation]}" if @config[:collation]
|
837
795
|
encoding << ", "
|
838
796
|
end
|
@@ -857,41 +815,24 @@ module ActiveRecord
|
|
857
815
|
end
|
858
816
|
end
|
859
817
|
|
860
|
-
def extract_foreign_key_action(specifier) # :nodoc:
|
861
|
-
case specifier
|
862
|
-
when "CASCADE"; :cascade
|
863
|
-
when "SET NULL"; :nullify
|
864
|
-
end
|
865
|
-
end
|
866
|
-
|
867
818
|
def create_table_info(table_name) # :nodoc:
|
868
819
|
exec_query("SHOW CREATE TABLE #{quote_table_name(table_name)}", "SCHEMA").first["Create Table"]
|
869
820
|
end
|
870
821
|
|
871
|
-
def
|
872
|
-
MySQL
|
822
|
+
def arel_visitor
|
823
|
+
Arel::Visitors::MySQL.new(self)
|
873
824
|
end
|
874
825
|
|
875
826
|
def mismatched_foreign_key(message)
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
REFERENCES\s*(`?(?<target_table>\w+)`?)\s*\(`?(?<primary_key>\w+)`?\)
|
880
|
-
/xmi.match(message)
|
881
|
-
|
882
|
-
options = {
|
827
|
+
parts = message.scan(/`(\w+)`[ $)]/).flatten
|
828
|
+
MismatchedForeignKey.new(
|
829
|
+
self,
|
883
830
|
message: message,
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
options[:target_table] = match[:target_table]
|
890
|
-
options[:primary_key] = match[:primary_key]
|
891
|
-
options[:primary_key_column] = column_for(match[:target_table], match[:primary_key])
|
892
|
-
end
|
893
|
-
|
894
|
-
MismatchedForeignKey.new(options)
|
831
|
+
table: parts[0],
|
832
|
+
foreign_key: parts[1],
|
833
|
+
target_table: parts[2],
|
834
|
+
primary_key: parts[3],
|
835
|
+
)
|
895
836
|
end
|
896
837
|
|
897
838
|
def integer_to_sql(limit) # :nodoc:
|
@@ -929,14 +870,11 @@ module ActiveRecord
|
|
929
870
|
full_version.match(/^(?:5\.5\.5-)?(\d+\.\d+\.\d+)/)[1]
|
930
871
|
end
|
931
872
|
|
932
|
-
class MysqlJson < Type::Internal::AbstractJson # :nodoc:
|
933
|
-
end
|
934
|
-
|
935
873
|
class MysqlString < Type::String # :nodoc:
|
936
874
|
def serialize(value)
|
937
875
|
case value
|
938
|
-
when true then
|
939
|
-
when false then
|
876
|
+
when true then "1"
|
877
|
+
when false then "0"
|
940
878
|
else super
|
941
879
|
end
|
942
880
|
end
|
@@ -945,14 +883,13 @@ module ActiveRecord
|
|
945
883
|
|
946
884
|
def cast_value(value)
|
947
885
|
case value
|
948
|
-
when true then
|
949
|
-
when false then
|
886
|
+
when true then "1"
|
887
|
+
when false then "0"
|
950
888
|
else super
|
951
889
|
end
|
952
890
|
end
|
953
891
|
end
|
954
892
|
|
955
|
-
ActiveRecord::Type.register(:json, MysqlJson, adapter: :mysql2)
|
956
893
|
ActiveRecord::Type.register(:string, MysqlString, adapter: :mysql2)
|
957
894
|
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql2)
|
958
895
|
end
|