activerecord 6.1.7 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1516 -1019
- data/MIT-LICENSE +1 -1
- data/README.rdoc +17 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +50 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +35 -31
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +26 -16
- data/lib/active_record/associations/preloader/association.rb +207 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +423 -289
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +61 -14
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +25 -10
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +10 -13
- data/lib/active_record/attribute_methods.rb +121 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +61 -30
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -51
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -136
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +622 -149
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +18 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +86 -52
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +381 -69
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +492 -230
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +65 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +107 -136
- data/lib/active_record/core.rb +194 -224
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +84 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +61 -15
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +224 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +172 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +96 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +156 -62
- data/lib/active_record/errors.rb +171 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +131 -86
- data/lib/active_record/future_result.rb +164 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +133 -20
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +117 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +36 -21
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +108 -13
- data/lib/active_record/migration/compatibility.rb +221 -48
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +355 -171
- data/lib/active_record/model_schema.rb +116 -97
- data/lib/active_record/nested_attributes.rb +36 -15
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +159 -0
- data/lib/active_record/persistence.rb +405 -85
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +219 -43
- data/lib/active_record/railties/controller_runtime.rb +13 -9
- data/lib/active_record/railties/databases.rake +185 -249
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +229 -80
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +211 -90
- data/lib/active_record/relation/delegation.rb +27 -13
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +654 -127
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +262 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +18 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +225 -136
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +116 -96
- data/lib/active_record/timestamp.rb +28 -17
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +139 -19
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +92 -13
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -3,6 +3,7 @@
|
|
3
3
|
require "active_record/connection_adapters/abstract_adapter"
|
4
4
|
require "active_record/connection_adapters/statement_pool"
|
5
5
|
require "active_record/connection_adapters/mysql/column"
|
6
|
+
require "active_record/connection_adapters/mysql/database_statements"
|
6
7
|
require "active_record/connection_adapters/mysql/explain_pretty_printer"
|
7
8
|
require "active_record/connection_adapters/mysql/quoting"
|
8
9
|
require "active_record/connection_adapters/mysql/schema_creation"
|
@@ -14,6 +15,7 @@ require "active_record/connection_adapters/mysql/type_metadata"
|
|
14
15
|
module ActiveRecord
|
15
16
|
module ConnectionAdapters
|
16
17
|
class AbstractMysqlAdapter < AbstractAdapter
|
18
|
+
include MySQL::DatabaseStatements
|
17
19
|
include MySQL::Quoting
|
18
20
|
include MySQL::SchemaStatements
|
19
21
|
|
@@ -31,6 +33,7 @@ module ActiveRecord
|
|
31
33
|
string: { name: "varchar", limit: 255 },
|
32
34
|
text: { name: "text" },
|
33
35
|
integer: { name: "int", limit: 4 },
|
36
|
+
bigint: { name: "bigint" },
|
34
37
|
float: { name: "float", limit: 24 },
|
35
38
|
decimal: { name: "decimal" },
|
36
39
|
datetime: { name: "datetime" },
|
@@ -50,11 +53,37 @@ module ActiveRecord
|
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
53
|
-
|
54
|
-
|
56
|
+
class << self
|
57
|
+
def dbconsole(config, options = {})
|
58
|
+
mysql_config = config.configuration_hash
|
59
|
+
|
60
|
+
args = {
|
61
|
+
host: "--host",
|
62
|
+
port: "--port",
|
63
|
+
socket: "--socket",
|
64
|
+
username: "--user",
|
65
|
+
encoding: "--default-character-set",
|
66
|
+
sslca: "--ssl-ca",
|
67
|
+
sslcert: "--ssl-cert",
|
68
|
+
sslcapath: "--ssl-capath",
|
69
|
+
sslcipher: "--ssl-cipher",
|
70
|
+
sslkey: "--ssl-key",
|
71
|
+
ssl_mode: "--ssl-mode"
|
72
|
+
}.filter_map { |opt, arg| "#{arg}=#{mysql_config[opt]}" if mysql_config[opt] }
|
73
|
+
|
74
|
+
if mysql_config[:password] && options[:include_password]
|
75
|
+
args << "--password=#{mysql_config[:password]}"
|
76
|
+
elsif mysql_config[:password] && !mysql_config[:password].to_s.empty?
|
77
|
+
args << "-p"
|
78
|
+
end
|
79
|
+
|
80
|
+
args << config.database
|
81
|
+
|
82
|
+
find_cmd_and_exec(["mysql", "mysql5"], *args)
|
83
|
+
end
|
55
84
|
end
|
56
85
|
|
57
|
-
def get_database_version
|
86
|
+
def get_database_version # :nodoc:
|
58
87
|
full_version_string = get_full_version
|
59
88
|
version_string = version_string(full_version_string)
|
60
89
|
Version.new(version_string, full_version_string)
|
@@ -80,6 +109,10 @@ module ActiveRecord
|
|
80
109
|
true
|
81
110
|
end
|
82
111
|
|
112
|
+
def supports_restart_db_transaction?
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
83
116
|
def supports_explain?
|
84
117
|
true
|
85
118
|
end
|
@@ -94,7 +127,7 @@ module ActiveRecord
|
|
94
127
|
|
95
128
|
def supports_check_constraints?
|
96
129
|
if mariadb?
|
97
|
-
database_version >= "10.2.
|
130
|
+
database_version >= "10.3.10" || (database_version < "10.3" && database_version >= "10.2.22")
|
98
131
|
else
|
99
132
|
database_version >= "8.0.16"
|
100
133
|
end
|
@@ -174,7 +207,7 @@ module ActiveRecord
|
|
174
207
|
|
175
208
|
# REFERENTIAL INTEGRITY ====================================
|
176
209
|
|
177
|
-
def disable_referential_integrity
|
210
|
+
def disable_referential_integrity # :nodoc:
|
178
211
|
old = query_value("SELECT @@FOREIGN_KEY_CHECKS")
|
179
212
|
|
180
213
|
begin
|
@@ -185,54 +218,43 @@ module ActiveRecord
|
|
185
218
|
end
|
186
219
|
end
|
187
220
|
|
188
|
-
# CONNECTION MANAGEMENT ====================================
|
189
|
-
|
190
|
-
def clear_cache! # :nodoc:
|
191
|
-
reload_type_map
|
192
|
-
super
|
193
|
-
end
|
194
|
-
|
195
221
|
#--
|
196
222
|
# DATABASE STATEMENTS ======================================
|
197
223
|
#++
|
198
224
|
|
199
|
-
# Executes the SQL statement in the context of this connection.
|
200
|
-
def execute(sql, name = nil)
|
201
|
-
materialize_transactions
|
202
|
-
mark_transaction_written_if_write(sql)
|
203
|
-
|
204
|
-
log(sql, name) do
|
205
|
-
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
206
|
-
@connection.query(sql)
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
225
|
# Mysql2Adapter doesn't have to free a result after using it, but we use this method
|
212
226
|
# to write stuff in an abstract way without concerning ourselves about whether it
|
213
227
|
# needs to be explicitly freed or not.
|
214
|
-
def execute_and_free(sql, name = nil) # :nodoc:
|
215
|
-
|
228
|
+
def execute_and_free(sql, name = nil, async: false) # :nodoc:
|
229
|
+
sql = transform_query(sql)
|
230
|
+
check_if_write_query(sql)
|
231
|
+
|
232
|
+
mark_transaction_written_if_write(sql)
|
233
|
+
yield raw_execute(sql, name, async: async)
|
216
234
|
end
|
217
235
|
|
218
|
-
def begin_db_transaction
|
219
|
-
|
236
|
+
def begin_db_transaction # :nodoc:
|
237
|
+
internal_execute("BEGIN", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
220
238
|
end
|
221
239
|
|
222
|
-
def begin_isolated_db_transaction(isolation)
|
223
|
-
|
240
|
+
def begin_isolated_db_transaction(isolation) # :nodoc:
|
241
|
+
internal_execute("SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
224
242
|
begin_db_transaction
|
225
243
|
end
|
226
244
|
|
227
|
-
def commit_db_transaction
|
228
|
-
|
245
|
+
def commit_db_transaction # :nodoc:
|
246
|
+
internal_execute("COMMIT", "TRANSACTION", allow_retry: false, materialize_transactions: true)
|
247
|
+
end
|
248
|
+
|
249
|
+
def exec_rollback_db_transaction # :nodoc:
|
250
|
+
internal_execute("ROLLBACK", "TRANSACTION", allow_retry: false, materialize_transactions: true)
|
229
251
|
end
|
230
252
|
|
231
|
-
def
|
232
|
-
|
253
|
+
def exec_restart_db_transaction # :nodoc:
|
254
|
+
internal_execute("ROLLBACK AND CHAIN", "TRANSACTION", allow_retry: false, materialize_transactions: true)
|
233
255
|
end
|
234
256
|
|
235
|
-
def empty_insert_statement_value(primary_key = nil)
|
257
|
+
def empty_insert_statement_value(primary_key = nil) # :nodoc:
|
236
258
|
"VALUES ()"
|
237
259
|
end
|
238
260
|
|
@@ -270,7 +292,7 @@ module ActiveRecord
|
|
270
292
|
#
|
271
293
|
# Example:
|
272
294
|
# drop_database('sebastian_development')
|
273
|
-
def drop_database(name)
|
295
|
+
def drop_database(name) # :nodoc:
|
274
296
|
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
|
275
297
|
end
|
276
298
|
|
@@ -309,7 +331,8 @@ module ActiveRecord
|
|
309
331
|
#
|
310
332
|
# Example:
|
311
333
|
# rename_table('octopuses', 'octopi')
|
312
|
-
def rename_table(table_name, new_name)
|
334
|
+
def rename_table(table_name, new_name, **options)
|
335
|
+
validate_table_length!(new_name) unless options[:_uses_legacy_table_name]
|
313
336
|
schema_cache.clear_data_source_cache!(table_name.to_s)
|
314
337
|
schema_cache.clear_data_source_cache!(new_name.to_s)
|
315
338
|
execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
|
@@ -346,12 +369,21 @@ module ActiveRecord
|
|
346
369
|
end
|
347
370
|
end
|
348
371
|
|
349
|
-
def change_column_default(table_name, column_name, default_or_changes)
|
372
|
+
def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
|
373
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{change_column_default_for_alter(table_name, column_name, default_or_changes)}"
|
374
|
+
end
|
375
|
+
|
376
|
+
def build_change_column_default_definition(table_name, column_name, default_or_changes) # :nodoc:
|
377
|
+
column = column_for(table_name, column_name)
|
378
|
+
return unless column
|
379
|
+
|
350
380
|
default = extract_new_default_value(default_or_changes)
|
351
|
-
|
381
|
+
ChangeColumnDefaultDefinition.new(column, default)
|
352
382
|
end
|
353
383
|
|
354
|
-
def change_column_null(table_name, column_name, null, default = nil)
|
384
|
+
def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
|
385
|
+
validate_change_column_null_argument!(null)
|
386
|
+
|
355
387
|
unless null || default.nil?
|
356
388
|
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
357
389
|
end
|
@@ -364,22 +396,64 @@ module ActiveRecord
|
|
364
396
|
change_column table_name, column_name, nil, comment: comment
|
365
397
|
end
|
366
398
|
|
367
|
-
def change_column(table_name, column_name, type, **options)
|
399
|
+
def change_column(table_name, column_name, type, **options) # :nodoc:
|
368
400
|
execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_for_alter(table_name, column_name, type, **options)}")
|
369
401
|
end
|
370
402
|
|
371
|
-
|
403
|
+
# Builds a ChangeColumnDefinition object.
|
404
|
+
#
|
405
|
+
# This definition object contains information about the column change that would occur
|
406
|
+
# if the same arguments were passed to #change_column. See #change_column for information about
|
407
|
+
# passing a +table_name+, +column_name+, +type+ and other options that can be passed.
|
408
|
+
def build_change_column_definition(table_name, column_name, type, **options) # :nodoc:
|
409
|
+
column = column_for(table_name, column_name)
|
410
|
+
type ||= column.sql_type
|
411
|
+
|
412
|
+
unless options.key?(:default)
|
413
|
+
options[:default] = column.default
|
414
|
+
end
|
415
|
+
|
416
|
+
unless options.key?(:null)
|
417
|
+
options[:null] = column.null
|
418
|
+
end
|
419
|
+
|
420
|
+
unless options.key?(:comment)
|
421
|
+
options[:comment] = column.comment
|
422
|
+
end
|
423
|
+
|
424
|
+
if options[:collation] == :no_collation
|
425
|
+
options.delete(:collation)
|
426
|
+
else
|
427
|
+
options[:collation] ||= column.collation if text_type?(type)
|
428
|
+
end
|
429
|
+
|
430
|
+
unless options.key?(:auto_increment)
|
431
|
+
options[:auto_increment] = column.auto_increment?
|
432
|
+
end
|
433
|
+
|
434
|
+
td = create_table_definition(table_name)
|
435
|
+
cd = td.new_column_definition(column.name, type, **options)
|
436
|
+
ChangeColumnDefinition.new(cd, column.name)
|
437
|
+
end
|
438
|
+
|
439
|
+
def rename_column(table_name, column_name, new_column_name) # :nodoc:
|
372
440
|
execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_for_alter(table_name, column_name, new_column_name)}")
|
373
441
|
rename_column_indexes(table_name, column_name, new_column_name)
|
374
442
|
end
|
375
443
|
|
376
|
-
def add_index(table_name, column_name, **options)
|
444
|
+
def add_index(table_name, column_name, **options) # :nodoc:
|
445
|
+
create_index = build_create_index_definition(table_name, column_name, **options)
|
446
|
+
return unless create_index
|
447
|
+
|
448
|
+
execute schema_creation.accept(create_index)
|
449
|
+
end
|
450
|
+
|
451
|
+
def build_create_index_definition(table_name, column_name, **options) # :nodoc:
|
377
452
|
index, algorithm, if_not_exists = add_index_options(table_name, column_name, **options)
|
378
453
|
|
379
454
|
return if if_not_exists && index_exists?(table_name, column_name, name: index.name)
|
380
455
|
|
381
|
-
|
382
|
-
execute schema_creation.accept(create_index)
|
456
|
+
CreateIndexDefinition.new(index, algorithm)
|
383
457
|
end
|
384
458
|
|
385
459
|
def add_sql_comment!(sql, comment) # :nodoc:
|
@@ -392,11 +466,13 @@ module ActiveRecord
|
|
392
466
|
|
393
467
|
scope = quoted_scope(table_name)
|
394
468
|
|
395
|
-
|
469
|
+
# MySQL returns 1 row for each column of composite foreign keys.
|
470
|
+
fk_info = internal_exec_query(<<~SQL, "SCHEMA")
|
396
471
|
SELECT fk.referenced_table_name AS 'to_table',
|
397
472
|
fk.referenced_column_name AS 'primary_key',
|
398
473
|
fk.column_name AS 'column',
|
399
474
|
fk.constraint_name AS 'name',
|
475
|
+
fk.ordinal_position AS 'position',
|
400
476
|
rc.update_rule AS 'on_update',
|
401
477
|
rc.delete_rule AS 'on_delete'
|
402
478
|
FROM information_schema.referential_constraints rc
|
@@ -409,17 +485,24 @@ module ActiveRecord
|
|
409
485
|
AND rc.table_name = #{scope[:name]}
|
410
486
|
SQL
|
411
487
|
|
412
|
-
fk_info.
|
488
|
+
grouped_fk = fk_info.group_by { |row| row["name"] }.values.each { |group| group.sort_by! { |row| row["position"] } }
|
489
|
+
grouped_fk.map do |group|
|
490
|
+
row = group.first
|
413
491
|
options = {
|
414
|
-
column: row["column"],
|
415
492
|
name: row["name"],
|
416
|
-
|
493
|
+
on_update: extract_foreign_key_action(row["on_update"]),
|
494
|
+
on_delete: extract_foreign_key_action(row["on_delete"])
|
417
495
|
}
|
418
496
|
|
419
|
-
|
420
|
-
|
497
|
+
if group.one?
|
498
|
+
options[:column] = unquote_identifier(row["column"])
|
499
|
+
options[:primary_key] = row["primary_key"]
|
500
|
+
else
|
501
|
+
options[:column] = group.map { |row| unquote_identifier(row["column"]) }
|
502
|
+
options[:primary_key] = group.map { |row| row["primary_key"] }
|
503
|
+
end
|
421
504
|
|
422
|
-
ForeignKeyDefinition.new(table_name, row["to_table"], options)
|
505
|
+
ForeignKeyDefinition.new(table_name, unquote_identifier(row["to_table"]), options)
|
423
506
|
end
|
424
507
|
end
|
425
508
|
|
@@ -427,7 +510,7 @@ module ActiveRecord
|
|
427
510
|
if supports_check_constraints?
|
428
511
|
scope = quoted_scope(table_name)
|
429
512
|
|
430
|
-
|
513
|
+
sql = <<~SQL
|
431
514
|
SELECT cc.constraint_name AS 'name',
|
432
515
|
cc.check_clause AS 'expression'
|
433
516
|
FROM information_schema.check_constraints cc
|
@@ -437,13 +520,24 @@ module ActiveRecord
|
|
437
520
|
AND tc.table_name = #{scope[:name]}
|
438
521
|
AND cc.constraint_schema = #{scope[:schema]}
|
439
522
|
SQL
|
523
|
+
sql += " AND cc.table_name = #{scope[:name]}" if mariadb?
|
524
|
+
|
525
|
+
chk_info = internal_exec_query(sql, "SCHEMA")
|
440
526
|
|
441
527
|
chk_info.map do |row|
|
442
528
|
options = {
|
443
529
|
name: row["name"]
|
444
530
|
}
|
445
531
|
expression = row["expression"]
|
446
|
-
expression = expression[1..-2]
|
532
|
+
expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
|
533
|
+
expression = strip_whitespace_characters(expression)
|
534
|
+
|
535
|
+
unless mariadb?
|
536
|
+
# MySQL returns check constraints expression in an already escaped form.
|
537
|
+
# This leads to duplicate escaping later (e.g. when the expression is used in the SchemaDumper).
|
538
|
+
expression = expression.gsub("\\'", "'")
|
539
|
+
end
|
540
|
+
|
447
541
|
CheckConstraintDefinition.new(table_name, expression, options)
|
448
542
|
end
|
449
543
|
else
|
@@ -548,8 +642,12 @@ module ActiveRecord
|
|
548
642
|
sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{no_op_column}"
|
549
643
|
elsif insert.update_duplicates?
|
550
644
|
sql << " ON DUPLICATE KEY UPDATE "
|
551
|
-
|
552
|
-
|
645
|
+
if insert.raw_update_sql?
|
646
|
+
sql << insert.raw_update_sql
|
647
|
+
else
|
648
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{column}<=>VALUES(#{column})" }
|
649
|
+
sql << insert.updatable_columns.map { |column| "#{column}=VALUES(#{column})" }.join(",")
|
650
|
+
end
|
553
651
|
end
|
554
652
|
|
555
653
|
sql
|
@@ -561,58 +659,99 @@ module ActiveRecord
|
|
561
659
|
end
|
562
660
|
end
|
563
661
|
|
564
|
-
|
565
|
-
def
|
566
|
-
super
|
662
|
+
class << self
|
663
|
+
def extended_type_map(default_timezone: nil, emulate_booleans:) # :nodoc:
|
664
|
+
super(default_timezone: default_timezone).tap do |m|
|
665
|
+
if emulate_booleans
|
666
|
+
m.register_type %r(^tinyint\(1\))i, Type::Boolean.new
|
667
|
+
end
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
private
|
672
|
+
def initialize_type_map(m)
|
673
|
+
super
|
674
|
+
|
675
|
+
m.register_type %r(tinytext)i, Type::Text.new(limit: 2**8 - 1)
|
676
|
+
m.register_type %r(tinyblob)i, Type::Binary.new(limit: 2**8 - 1)
|
677
|
+
m.register_type %r(text)i, Type::Text.new(limit: 2**16 - 1)
|
678
|
+
m.register_type %r(blob)i, Type::Binary.new(limit: 2**16 - 1)
|
679
|
+
m.register_type %r(mediumtext)i, Type::Text.new(limit: 2**24 - 1)
|
680
|
+
m.register_type %r(mediumblob)i, Type::Binary.new(limit: 2**24 - 1)
|
681
|
+
m.register_type %r(longtext)i, Type::Text.new(limit: 2**32 - 1)
|
682
|
+
m.register_type %r(longblob)i, Type::Binary.new(limit: 2**32 - 1)
|
683
|
+
m.register_type %r(^float)i, Type::Float.new(limit: 24)
|
684
|
+
m.register_type %r(^double)i, Type::Float.new(limit: 53)
|
685
|
+
|
686
|
+
register_integer_type m, %r(^bigint)i, limit: 8
|
687
|
+
register_integer_type m, %r(^int)i, limit: 4
|
688
|
+
register_integer_type m, %r(^mediumint)i, limit: 3
|
689
|
+
register_integer_type m, %r(^smallint)i, limit: 2
|
690
|
+
register_integer_type m, %r(^tinyint)i, limit: 1
|
691
|
+
|
692
|
+
m.alias_type %r(year)i, "integer"
|
693
|
+
m.alias_type %r(bit)i, "binary"
|
694
|
+
end
|
567
695
|
|
568
|
-
|
569
|
-
|
570
|
-
|
696
|
+
def register_integer_type(mapping, key, **options)
|
697
|
+
mapping.register_type(key) do |sql_type|
|
698
|
+
if /\bunsigned\b/.match?(sql_type)
|
699
|
+
Type::UnsignedInteger.new(**options)
|
700
|
+
else
|
701
|
+
Type::Integer.new(**options)
|
702
|
+
end
|
703
|
+
end
|
571
704
|
end
|
572
705
|
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
m.register_type %r(blob)i, Type::Binary.new(limit: 2**16 - 1)
|
577
|
-
m.register_type %r(mediumtext)i, Type::Text.new(limit: 2**24 - 1)
|
578
|
-
m.register_type %r(mediumblob)i, Type::Binary.new(limit: 2**24 - 1)
|
579
|
-
m.register_type %r(longtext)i, Type::Text.new(limit: 2**32 - 1)
|
580
|
-
m.register_type %r(longblob)i, Type::Binary.new(limit: 2**32 - 1)
|
581
|
-
m.register_type %r(^float)i, Type::Float.new(limit: 24)
|
582
|
-
m.register_type %r(^double)i, Type::Float.new(limit: 53)
|
583
|
-
|
584
|
-
register_integer_type m, %r(^bigint)i, limit: 8
|
585
|
-
register_integer_type m, %r(^int)i, limit: 4
|
586
|
-
register_integer_type m, %r(^mediumint)i, limit: 3
|
587
|
-
register_integer_type m, %r(^smallint)i, limit: 2
|
588
|
-
register_integer_type m, %r(^tinyint)i, limit: 1
|
589
|
-
|
590
|
-
m.register_type %r(^tinyint\(1\))i, Type::Boolean.new if emulate_booleans
|
591
|
-
m.alias_type %r(year)i, "integer"
|
592
|
-
m.alias_type %r(bit)i, "binary"
|
593
|
-
|
594
|
-
m.register_type %r(^enum)i, Type.lookup(:string, adapter: :mysql2)
|
595
|
-
m.register_type %r(^set)i, Type.lookup(:string, adapter: :mysql2)
|
596
|
-
end
|
597
|
-
|
598
|
-
def register_integer_type(mapping, key, **options)
|
599
|
-
mapping.register_type(key) do |sql_type|
|
600
|
-
if /\bunsigned\b/.match?(sql_type)
|
601
|
-
Type::UnsignedInteger.new(**options)
|
706
|
+
def extract_precision(sql_type)
|
707
|
+
if /\A(?:date)?time(?:stamp)?\b/.match?(sql_type)
|
708
|
+
super || 0
|
602
709
|
else
|
603
|
-
|
710
|
+
super
|
604
711
|
end
|
605
712
|
end
|
713
|
+
end
|
714
|
+
|
715
|
+
EXTENDED_TYPE_MAPS = Concurrent::Map.new
|
716
|
+
EMULATE_BOOLEANS_TRUE = { emulate_booleans: true }.freeze
|
717
|
+
|
718
|
+
private
|
719
|
+
def strip_whitespace_characters(expression)
|
720
|
+
expression = expression.gsub(/\\n|\\\\/, "")
|
721
|
+
expression = expression.gsub(/\s{2,}/, " ")
|
722
|
+
expression
|
606
723
|
end
|
607
724
|
|
608
|
-
def
|
609
|
-
if
|
610
|
-
|
611
|
-
|
612
|
-
|
725
|
+
def extended_type_map_key
|
726
|
+
if @default_timezone
|
727
|
+
{ default_timezone: @default_timezone, emulate_booleans: emulate_booleans }
|
728
|
+
elsif emulate_booleans
|
729
|
+
EMULATE_BOOLEANS_TRUE
|
613
730
|
end
|
614
731
|
end
|
615
732
|
|
733
|
+
def handle_warnings(sql)
|
734
|
+
return if ActiveRecord.db_warnings_action.nil? || @raw_connection.warning_count == 0
|
735
|
+
|
736
|
+
@affected_rows_before_warnings = @raw_connection.affected_rows
|
737
|
+
result = @raw_connection.query("SHOW WARNINGS")
|
738
|
+
result.each do |level, code, message|
|
739
|
+
warning = SQLWarning.new(message, code, level, sql, @pool)
|
740
|
+
next if warning_ignored?(warning)
|
741
|
+
|
742
|
+
ActiveRecord.db_warnings_action.call(warning)
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
def warning_ignored?(warning)
|
747
|
+
warning.level == "Note" || super
|
748
|
+
end
|
749
|
+
|
750
|
+
# Make sure we carry over any changes to ActiveRecord.default_timezone that have been
|
751
|
+
# made since we established the connection
|
752
|
+
def sync_timezone_changes(raw_connection)
|
753
|
+
end
|
754
|
+
|
616
755
|
# See https://dev.mysql.com/doc/mysql-errors/en/server-error-reference.html
|
617
756
|
ER_DB_CREATE_EXISTS = 1007
|
618
757
|
ER_FILSORT_ABORT = 1028
|
@@ -630,69 +769,59 @@ module ActiveRecord
|
|
630
769
|
ER_CANNOT_CREATE_TABLE = 1005
|
631
770
|
ER_LOCK_WAIT_TIMEOUT = 1205
|
632
771
|
ER_QUERY_INTERRUPTED = 1317
|
772
|
+
ER_CONNECTION_KILLED = 1927
|
773
|
+
CR_SERVER_GONE_ERROR = 2006
|
774
|
+
CR_SERVER_LOST = 2013
|
633
775
|
ER_QUERY_TIMEOUT = 3024
|
634
776
|
ER_FK_INCOMPATIBLE_COLUMNS = 3780
|
777
|
+
ER_CLIENT_INTERACTION_TIMEOUT = 4031
|
635
778
|
|
636
779
|
def translate_exception(exception, message:, sql:, binds:)
|
637
780
|
case error_number(exception)
|
638
781
|
when nil
|
639
782
|
if exception.message.match?(/MySQL client is not connected/i)
|
640
|
-
ConnectionNotEstablished.new(exception)
|
783
|
+
ConnectionNotEstablished.new(exception, connection_pool: @pool)
|
641
784
|
else
|
642
785
|
super
|
643
786
|
end
|
787
|
+
when ER_CONNECTION_KILLED, CR_SERVER_GONE_ERROR, CR_SERVER_LOST, ER_CLIENT_INTERACTION_TIMEOUT
|
788
|
+
ConnectionFailed.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
644
789
|
when ER_DB_CREATE_EXISTS
|
645
|
-
DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
|
790
|
+
DatabaseAlreadyExists.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
646
791
|
when ER_DUP_ENTRY
|
647
|
-
RecordNotUnique.new(message, sql: sql, binds: binds)
|
792
|
+
RecordNotUnique.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
648
793
|
when ER_NO_REFERENCED_ROW, ER_ROW_IS_REFERENCED, ER_ROW_IS_REFERENCED_2, ER_NO_REFERENCED_ROW_2
|
649
|
-
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
794
|
+
InvalidForeignKey.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
650
795
|
when ER_CANNOT_ADD_FOREIGN, ER_FK_INCOMPATIBLE_COLUMNS
|
651
|
-
mismatched_foreign_key(message, sql: sql, binds: binds)
|
796
|
+
mismatched_foreign_key(message, sql: sql, binds: binds, connection_pool: @pool)
|
652
797
|
when ER_CANNOT_CREATE_TABLE
|
653
798
|
if message.include?("errno: 150")
|
654
|
-
mismatched_foreign_key(message, sql: sql, binds: binds)
|
799
|
+
mismatched_foreign_key(message, sql: sql, binds: binds, connection_pool: @pool)
|
655
800
|
else
|
656
801
|
super
|
657
802
|
end
|
658
803
|
when ER_DATA_TOO_LONG
|
659
|
-
ValueTooLong.new(message, sql: sql, binds: binds)
|
804
|
+
ValueTooLong.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
660
805
|
when ER_OUT_OF_RANGE
|
661
|
-
RangeError.new(message, sql: sql, binds: binds)
|
806
|
+
RangeError.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
662
807
|
when ER_NOT_NULL_VIOLATION, ER_DO_NOT_HAVE_DEFAULT
|
663
|
-
NotNullViolation.new(message, sql: sql, binds: binds)
|
808
|
+
NotNullViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
664
809
|
when ER_LOCK_DEADLOCK
|
665
|
-
Deadlocked.new(message, sql: sql, binds: binds)
|
810
|
+
Deadlocked.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
666
811
|
when ER_LOCK_WAIT_TIMEOUT
|
667
|
-
LockWaitTimeout.new(message, sql: sql, binds: binds)
|
812
|
+
LockWaitTimeout.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
668
813
|
when ER_QUERY_TIMEOUT, ER_FILSORT_ABORT
|
669
|
-
StatementTimeout.new(message, sql: sql, binds: binds)
|
814
|
+
StatementTimeout.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
670
815
|
when ER_QUERY_INTERRUPTED
|
671
|
-
QueryCanceled.new(message, sql: sql, binds: binds)
|
816
|
+
QueryCanceled.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
672
817
|
else
|
673
818
|
super
|
674
819
|
end
|
675
820
|
end
|
676
821
|
|
677
822
|
def change_column_for_alter(table_name, column_name, type, **options)
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
unless options.key?(:default)
|
682
|
-
options[:default] = column.default
|
683
|
-
end
|
684
|
-
|
685
|
-
unless options.key?(:null)
|
686
|
-
options[:null] = column.null
|
687
|
-
end
|
688
|
-
|
689
|
-
unless options.key?(:comment)
|
690
|
-
options[:comment] = column.comment
|
691
|
-
end
|
692
|
-
|
693
|
-
td = create_table_definition(table_name)
|
694
|
-
cd = td.new_column_definition(column.name, type, **options)
|
695
|
-
schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
|
823
|
+
cd = build_change_column_definition(table_name, column_name, type, **options)
|
824
|
+
schema_creation.accept(cd)
|
696
825
|
end
|
697
826
|
|
698
827
|
def rename_column_for_alter(table_name, column_name, new_column_name)
|
@@ -706,7 +835,7 @@ module ActiveRecord
|
|
706
835
|
comment: column.comment
|
707
836
|
}
|
708
837
|
|
709
|
-
current_type =
|
838
|
+
current_type = internal_exec_query("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE #{quote(column_name)}", "SCHEMA").first["Type"]
|
710
839
|
td = create_table_definition(table_name)
|
711
840
|
cd = td.new_column_definition(new_column_name, current_type, **options)
|
712
841
|
schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
|
@@ -743,9 +872,6 @@ module ActiveRecord
|
|
743
872
|
def configure_connection
|
744
873
|
variables = @config.fetch(:variables, {}).stringify_keys
|
745
874
|
|
746
|
-
# By default, MySQL 'where id is null' selects the last inserted id; Turn this off.
|
747
|
-
variables["sql_auto_is_null"] = 0
|
748
|
-
|
749
875
|
# Increase timeout so the server doesn't disconnect us.
|
750
876
|
wait_timeout = self.class.type_cast_config_to_integer(@config[:wait_timeout])
|
751
877
|
wait_timeout = 2147483 unless wait_timeout.is_a?(Integer)
|
@@ -780,17 +906,16 @@ module ActiveRecord
|
|
780
906
|
end
|
781
907
|
|
782
908
|
# Gather up all of the SET variables...
|
783
|
-
variable_assignments = variables.
|
909
|
+
variable_assignments = variables.filter_map do |k, v|
|
784
910
|
if defaults.include?(v)
|
785
911
|
"@@SESSION.#{k} = DEFAULT" # Sets the value to the global or compile default
|
786
912
|
elsif !v.nil?
|
787
913
|
"@@SESSION.#{k} = #{quote(v)}"
|
788
914
|
end
|
789
|
-
|
790
|
-
end.compact.join(", ")
|
915
|
+
end.join(", ")
|
791
916
|
|
792
917
|
# ...and send them all in one query
|
793
|
-
|
918
|
+
internal_execute("SET #{encoding} #{sql_mode_assignment} #{variable_assignments}")
|
794
919
|
end
|
795
920
|
|
796
921
|
def column_definitions(table_name) # :nodoc:
|
@@ -800,7 +925,7 @@ module ActiveRecord
|
|
800
925
|
end
|
801
926
|
|
802
927
|
def create_table_info(table_name) # :nodoc:
|
803
|
-
|
928
|
+
internal_exec_query("SHOW CREATE TABLE #{quote_table_name(table_name)}", "SCHEMA").first["Create Table"]
|
804
929
|
end
|
805
930
|
|
806
931
|
def arel_visitor
|
@@ -811,18 +936,17 @@ module ActiveRecord
|
|
811
936
|
StatementPool.new(self.class.type_cast_config_to_integer(@config[:statement_limit]))
|
812
937
|
end
|
813
938
|
|
814
|
-
def
|
939
|
+
def mismatched_foreign_key_details(message:, sql:)
|
940
|
+
foreign_key_pat =
|
941
|
+
/Referencing column '(\w+)' and referenced/i =~ message ? $1 : '\w+'
|
942
|
+
|
815
943
|
match = %r/
|
816
944
|
(?:CREATE|ALTER)\s+TABLE\s*(?:`?\w+`?\.)?`?(?<table>\w+)`?.+?
|
817
|
-
FOREIGN\s+KEY\s*\(`?(?<foreign_key
|
945
|
+
FOREIGN\s+KEY\s*\(`?(?<foreign_key>#{foreign_key_pat})`?\)\s*
|
818
946
|
REFERENCES\s*(`?(?<target_table>\w+)`?)\s*\(`?(?<primary_key>\w+)`?\)
|
819
947
|
/xmi.match(sql)
|
820
948
|
|
821
|
-
options = {
|
822
|
-
message: message,
|
823
|
-
sql: sql,
|
824
|
-
binds: binds,
|
825
|
-
}
|
949
|
+
options = {}
|
826
950
|
|
827
951
|
if match
|
828
952
|
options[:table] = match[:table]
|
@@ -832,24 +956,29 @@ module ActiveRecord
|
|
832
956
|
options[:primary_key_column] = column_for(match[:target_table], match[:primary_key])
|
833
957
|
end
|
834
958
|
|
835
|
-
|
959
|
+
options
|
836
960
|
end
|
837
961
|
|
838
|
-
def
|
839
|
-
|
840
|
-
|
962
|
+
def mismatched_foreign_key(message, sql:, binds:, connection_pool:)
|
963
|
+
options = {
|
964
|
+
message: message,
|
965
|
+
sql: sql,
|
966
|
+
binds: binds,
|
967
|
+
connection_pool: connection_pool
|
968
|
+
}
|
841
969
|
|
842
|
-
|
843
|
-
|
844
|
-
|
970
|
+
if sql
|
971
|
+
options.update mismatched_foreign_key_details(message: message, sql: sql)
|
972
|
+
else
|
973
|
+
options[:query_parser] = ->(sql) { mismatched_foreign_key_details(message: message, sql: sql) }
|
974
|
+
end
|
845
975
|
|
846
|
-
|
847
|
-
Type::ImmutableString.new(true: "1", false: "0", **args)
|
976
|
+
MismatchedForeignKey.new(**options)
|
848
977
|
end
|
849
|
-
|
850
|
-
|
978
|
+
|
979
|
+
def version_string(full_version_string)
|
980
|
+
full_version_string.match(/^(?:5\.5\.5-)?(\d+\.\d+\.\d+)/)[1]
|
851
981
|
end
|
852
|
-
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql2)
|
853
982
|
end
|
854
983
|
end
|
855
984
|
end
|