activerecord 8.0.0 → 8.1.4
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 +1381 -241
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -17
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +20 -4
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +36 -8
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +9 -5
- data/lib/active_record/associations/collection_proxy.rb +26 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_one_association.rb +1 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +5 -4
- data/lib/active_record/associations/preloader/association.rb +1 -1
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations.rb +159 -21
- data/lib/active_record/attribute_methods/primary_key.rb +2 -1
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +19 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +10 -2
- data/lib/active_record/attribute_methods.rb +24 -17
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +22 -12
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/column_serializer.rb +1 -1
- data/lib/active_record/coders/json.rb +16 -6
- data/lib/active_record/coders/yaml_column.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +19 -18
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +474 -112
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +68 -41
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -24
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +31 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +94 -28
- data/lib/active_record/connection_adapters/abstract/transaction.rb +25 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -64
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -40
- data/lib/active_record/connection_adapters/column.rb +14 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +42 -5
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +40 -25
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +66 -15
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +29 -33
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +70 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +99 -54
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +40 -12
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +39 -23
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +15 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +7 -14
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +68 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +8 -3
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -2
- data/lib/active_record/connection_adapters.rb +1 -0
- data/lib/active_record/connection_handling.rb +15 -10
- data/lib/active_record/core.rb +44 -12
- data/lib/active_record/counter_cache.rb +36 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +5 -1
- data/lib/active_record/database_configurations/hash_config.rb +66 -9
- data/lib/active_record/database_configurations/url_config.rb +15 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/disable_joins_association_relation.rb +5 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
- data/lib/active_record/encryption/encryptor.rb +39 -25
- data/lib/active_record/encryption/scheme.rb +1 -1
- data/lib/active_record/enum.rb +37 -20
- data/lib/active_record/errors.rb +23 -7
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +76 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -2
- data/lib/active_record/future_result.rb +5 -3
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +9 -4
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +7 -0
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +30 -22
- data/lib/active_record/message_pack.rb +13 -0
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +32 -6
- data/lib/active_record/migration/compatibility.rb +34 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +31 -21
- data/lib/active_record/model_schema.rb +38 -12
- data/lib/active_record/nested_attributes.rb +10 -6
- data/lib/active_record/persistence.rb +35 -3
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +7 -7
- data/lib/active_record/querying.rb +17 -5
- data/lib/active_record/railtie.rb +35 -6
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +24 -20
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +36 -1
- data/lib/active_record/relation/batches.rb +25 -11
- data/lib/active_record/relation/calculations.rb +62 -41
- data/lib/active_record/relation/delegation.rb +0 -1
- data/lib/active_record/relation/finder_methods.rb +76 -45
- data/lib/active_record/relation/merger.rb +4 -2
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +7 -7
- data/lib/active_record/relation/predicate_builder.rb +10 -8
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +106 -45
- data/lib/active_record/relation/spawn_methods.rb +6 -6
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +63 -31
- data/lib/active_record/result.rb +44 -21
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +2 -0
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +41 -21
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +48 -19
- data/lib/active_record/statement_cache.rb +16 -12
- data/lib/active_record/store.rb +46 -19
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +5 -20
- data/lib/active_record/tasks/abstract_tasks.rb +83 -0
- data/lib/active_record/tasks/database_tasks.rb +44 -45
- data/lib/active_record/tasks/mysql_database_tasks.rb +4 -56
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -26
- data/lib/active_record/test_databases.rb +18 -4
- data/lib/active_record/test_fixtures.rb +40 -6
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +58 -32
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +13 -2
- data/lib/active_record/type/serialized.rb +16 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +72 -7
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +7 -23
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +16 -15
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
|
@@ -28,6 +28,21 @@ module ActiveRecord
|
|
|
28
28
|
# ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
|
|
29
29
|
class_attribute :emulate_booleans, default: true
|
|
30
30
|
|
|
31
|
+
class_attribute :cli_arg_map, instance_accessor: false, default: {
|
|
32
|
+
host: "--host",
|
|
33
|
+
port: "--port",
|
|
34
|
+
socket: "--socket",
|
|
35
|
+
username: "--user",
|
|
36
|
+
password: "--password",
|
|
37
|
+
encoding: "--default-character-set",
|
|
38
|
+
sslca: "--ssl-ca",
|
|
39
|
+
sslcert: "--ssl-cert",
|
|
40
|
+
sslcapath: "--ssl-capath",
|
|
41
|
+
sslcipher: "--ssl-cipher",
|
|
42
|
+
sslkey: "--ssl-key",
|
|
43
|
+
ssl_mode: "--ssl-mode"
|
|
44
|
+
}.freeze
|
|
45
|
+
|
|
31
46
|
NATIVE_DATABASE_TYPES = {
|
|
32
47
|
primary_key: "bigint auto_increment PRIMARY KEY",
|
|
33
48
|
string: { name: "varchar", limit: 255 },
|
|
@@ -42,7 +57,7 @@ module ActiveRecord
|
|
|
42
57
|
date: { name: "date" },
|
|
43
58
|
binary: { name: "blob" },
|
|
44
59
|
blob: { name: "blob" },
|
|
45
|
-
boolean: { name: "
|
|
60
|
+
boolean: { name: "boolean" },
|
|
46
61
|
json: { name: "json" },
|
|
47
62
|
}
|
|
48
63
|
|
|
@@ -54,22 +69,14 @@ module ActiveRecord
|
|
|
54
69
|
end
|
|
55
70
|
|
|
56
71
|
class << self
|
|
72
|
+
def cli_args(config) # :nodoc:
|
|
73
|
+
cli_arg_map.filter_map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }
|
|
74
|
+
end
|
|
75
|
+
|
|
57
76
|
def dbconsole(config, options = {})
|
|
58
77
|
mysql_config = config.configuration_hash
|
|
59
78
|
|
|
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] }
|
|
79
|
+
args = cli_args(mysql_config.except(:password))
|
|
73
80
|
|
|
74
81
|
if mysql_config[:password] && options[:include_password]
|
|
75
82
|
args << "--password=#{mysql_config[:password]}"
|
|
@@ -81,6 +88,10 @@ module ActiveRecord
|
|
|
81
88
|
|
|
82
89
|
find_cmd_and_exec(ActiveRecord.database_cli[:mysql], *args)
|
|
83
90
|
end
|
|
91
|
+
|
|
92
|
+
def native_database_types # :nodoc:
|
|
93
|
+
NATIVE_DATABASE_TYPES
|
|
94
|
+
end
|
|
84
95
|
end
|
|
85
96
|
|
|
86
97
|
def get_database_version # :nodoc:
|
|
@@ -174,6 +185,30 @@ module ActiveRecord
|
|
|
174
185
|
mariadb? && database_version >= "10.5.0"
|
|
175
186
|
end
|
|
176
187
|
|
|
188
|
+
def return_value_after_insert?(column) # :nodoc:
|
|
189
|
+
supports_insert_returning? ? column.auto_populated? : column.auto_increment?
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# See https://dev.mysql.com/doc/refman/8.0/en/invisible-indexes.html for more details on MySQL feature.
|
|
193
|
+
# See https://mariadb.com/kb/en/ignored-indexes/ for more details on the MariaDB feature.
|
|
194
|
+
def supports_disabling_indexes?
|
|
195
|
+
if mariadb?
|
|
196
|
+
database_version >= "10.6.0"
|
|
197
|
+
else
|
|
198
|
+
database_version >= "8.0.0"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def create_or_find_by_lock # :nodoc:
|
|
203
|
+
# A shared lock provides a current read under REPEATABLE READ without
|
|
204
|
+
# upgrading the shared record lock acquired by a duplicate INSERT.
|
|
205
|
+
if mariadb? || database_version < "8.0.1"
|
|
206
|
+
"LOCK IN SHARE MODE"
|
|
207
|
+
else
|
|
208
|
+
"FOR SHARE"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
177
212
|
def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
|
|
178
213
|
query_value("SELECT GET_LOCK(#{quote(lock_name.to_s)}, #{timeout})") == 1
|
|
179
214
|
end
|
|
@@ -182,10 +217,6 @@ module ActiveRecord
|
|
|
182
217
|
query_value("SELECT RELEASE_LOCK(#{quote(lock_name.to_s)})") == 1
|
|
183
218
|
end
|
|
184
219
|
|
|
185
|
-
def native_database_types
|
|
186
|
-
NATIVE_DATABASE_TYPES
|
|
187
|
-
end
|
|
188
|
-
|
|
189
220
|
def index_algorithms
|
|
190
221
|
{
|
|
191
222
|
default: "ALGORITHM = DEFAULT",
|
|
@@ -195,8 +226,6 @@ module ActiveRecord
|
|
|
195
226
|
}
|
|
196
227
|
end
|
|
197
228
|
|
|
198
|
-
# HELPER METHODS ===========================================
|
|
199
|
-
|
|
200
229
|
# Must return the MySQL error number from the exception, if the exception has an
|
|
201
230
|
# error number.
|
|
202
231
|
def error_number(exception) # :nodoc:
|
|
@@ -227,12 +256,24 @@ module ActiveRecord
|
|
|
227
256
|
def begin_isolated_db_transaction(isolation) # :nodoc:
|
|
228
257
|
# From MySQL manual: The [SET TRANSACTION] statement applies only to the next single transaction performed within the session.
|
|
229
258
|
# So we don't need to implement #reset_isolation_level
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
259
|
+
if multi_statements_enabled?
|
|
260
|
+
execute_batch(
|
|
261
|
+
["SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}", "BEGIN"],
|
|
262
|
+
"TRANSACTION",
|
|
263
|
+
allow_retry: true,
|
|
264
|
+
materialize_transactions: false,
|
|
265
|
+
)
|
|
266
|
+
else
|
|
267
|
+
with_raw_connection(allow_retry: true, materialize_transactions: false) do
|
|
268
|
+
internal_execute(
|
|
269
|
+
"SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}",
|
|
270
|
+
"TRANSACTION",
|
|
271
|
+
allow_retry: false,
|
|
272
|
+
materialize_transactions: false,
|
|
273
|
+
)
|
|
274
|
+
internal_execute("BEGIN", "TRANSACTION", allow_retry: false, materialize_transactions: false)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
236
277
|
end
|
|
237
278
|
|
|
238
279
|
def commit_db_transaction # :nodoc:
|
|
@@ -403,7 +444,11 @@ module ActiveRecord
|
|
|
403
444
|
type ||= column.sql_type
|
|
404
445
|
|
|
405
446
|
unless options.key?(:default)
|
|
406
|
-
options[:default] = column.
|
|
447
|
+
options[:default] = if column.default_function
|
|
448
|
+
-> { column.default_function }
|
|
449
|
+
else
|
|
450
|
+
column.default
|
|
451
|
+
end
|
|
407
452
|
end
|
|
408
453
|
|
|
409
454
|
unless options.key?(:null)
|
|
@@ -449,6 +494,24 @@ module ActiveRecord
|
|
|
449
494
|
CreateIndexDefinition.new(index, algorithm)
|
|
450
495
|
end
|
|
451
496
|
|
|
497
|
+
def enable_index(table_name, index_name) # :nodoc:
|
|
498
|
+
raise NotImplementedError unless supports_disabling_indexes?
|
|
499
|
+
|
|
500
|
+
query = <<~SQL
|
|
501
|
+
ALTER TABLE #{quote_table_name(table_name)} ALTER INDEX #{quote_column_name(index_name)} #{mariadb? ? "NOT IGNORED" : "VISIBLE"}
|
|
502
|
+
SQL
|
|
503
|
+
execute(query)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def disable_index(table_name, index_name) # :nodoc:
|
|
507
|
+
raise NotImplementedError unless supports_disabling_indexes?
|
|
508
|
+
|
|
509
|
+
query = <<~SQL
|
|
510
|
+
ALTER TABLE #{quote_table_name(table_name)} ALTER INDEX #{quote_column_name(index_name)} #{mariadb? ? "IGNORED" : "INVISIBLE"}
|
|
511
|
+
SQL
|
|
512
|
+
execute(query)
|
|
513
|
+
end
|
|
514
|
+
|
|
452
515
|
def add_sql_comment!(sql, comment) # :nodoc:
|
|
453
516
|
sql << " COMMENT #{quote(comment)}" if comment.present?
|
|
454
517
|
sql
|
|
@@ -628,24 +691,26 @@ module ActiveRecord
|
|
|
628
691
|
end
|
|
629
692
|
|
|
630
693
|
def build_insert_sql(insert) # :nodoc:
|
|
694
|
+
# Can use any column as it will be assigned to itself.
|
|
631
695
|
no_op_column = quote_column_name(insert.keys.first) if insert.keys.first
|
|
632
696
|
|
|
633
697
|
# MySQL 8.0.19 replaces `VALUES(<expression>)` clauses with row and column alias names, see https://dev.mysql.com/worklog/task/?id=6312 .
|
|
634
698
|
# then MySQL 8.0.20 deprecates the `VALUES(<expression>)` see https://dev.mysql.com/worklog/task/?id=13325 .
|
|
635
699
|
if supports_insert_raw_alias_syntax?
|
|
700
|
+
quoted_table_name = insert.model.quoted_table_name
|
|
636
701
|
values_alias = quote_table_name("#{insert.model.table_name.parameterize}_values")
|
|
637
702
|
sql = +"INSERT #{insert.into} #{insert.values_list} AS #{values_alias}"
|
|
638
703
|
|
|
639
704
|
if insert.skip_duplicates?
|
|
640
705
|
if no_op_column
|
|
641
|
-
sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{
|
|
706
|
+
sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{quoted_table_name}.#{no_op_column}"
|
|
642
707
|
end
|
|
643
708
|
elsif insert.update_duplicates?
|
|
644
709
|
if insert.raw_update_sql?
|
|
645
710
|
sql = +"INSERT #{insert.into} #{insert.values_list} ON DUPLICATE KEY UPDATE #{insert.raw_update_sql}"
|
|
646
711
|
else
|
|
647
712
|
sql << " ON DUPLICATE KEY UPDATE "
|
|
648
|
-
sql << insert.touch_model_timestamps_unless { |column| "#{
|
|
713
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{quoted_table_name}.#{column}<=>#{values_alias}.#{column}" }
|
|
649
714
|
sql << insert.updatable_columns.map { |column| "#{column}=#{values_alias}.#{column}" }.join(",")
|
|
650
715
|
end
|
|
651
716
|
end
|
|
@@ -722,12 +787,12 @@ module ActiveRecord
|
|
|
722
787
|
m.alias_type %r(bit)i, "binary"
|
|
723
788
|
end
|
|
724
789
|
|
|
725
|
-
def register_integer_type(mapping, key,
|
|
790
|
+
def register_integer_type(mapping, key, limit:)
|
|
726
791
|
mapping.register_type(key) do |sql_type|
|
|
727
792
|
if /\bunsigned\b/.match?(sql_type)
|
|
728
|
-
Type::UnsignedInteger.new(
|
|
793
|
+
Type::UnsignedInteger.new(limit: limit)
|
|
729
794
|
else
|
|
730
|
-
Type::Integer.new(
|
|
795
|
+
Type::Integer.new(limit: limit)
|
|
731
796
|
end
|
|
732
797
|
end
|
|
733
798
|
end
|
|
@@ -746,9 +811,7 @@ module ActiveRecord
|
|
|
746
811
|
|
|
747
812
|
private
|
|
748
813
|
def strip_whitespace_characters(expression)
|
|
749
|
-
expression
|
|
750
|
-
expression = expression.gsub(/\s{2,}/, " ")
|
|
751
|
-
expression
|
|
814
|
+
expression.gsub('\\\n', "").gsub("x0A", "").squish
|
|
752
815
|
end
|
|
753
816
|
|
|
754
817
|
def extended_type_map_key
|
|
@@ -759,14 +822,13 @@ module ActiveRecord
|
|
|
759
822
|
end
|
|
760
823
|
end
|
|
761
824
|
|
|
762
|
-
def handle_warnings(sql)
|
|
825
|
+
def handle_warnings(_initial_result, sql)
|
|
763
826
|
return if ActiveRecord.db_warnings_action.nil? || @raw_connection.warning_count == 0
|
|
764
827
|
|
|
765
|
-
@affected_rows_before_warnings = @raw_connection.affected_rows
|
|
766
828
|
warning_count = @raw_connection.warning_count
|
|
767
829
|
result = @raw_connection.query("SHOW WARNINGS")
|
|
768
830
|
result = [
|
|
769
|
-
["Warning", nil, "Query had warning_count=#{warning_count} but
|
|
831
|
+
["Warning", nil, "Query had warning_count=#{warning_count} but `SHOW WARNINGS` did not return the warnings. Check MySQL logs or database configuration."],
|
|
770
832
|
] if result.count == 0
|
|
771
833
|
result.each do |level, code, message|
|
|
772
834
|
warning = SQLWarning.new(message, code, level, sql, @pool)
|
|
@@ -783,6 +845,7 @@ module ActiveRecord
|
|
|
783
845
|
# See https://dev.mysql.com/doc/mysql-errors/en/server-error-reference.html
|
|
784
846
|
ER_DB_CREATE_EXISTS = 1007
|
|
785
847
|
ER_FILSORT_ABORT = 1028
|
|
848
|
+
ER_NO_DB_ERROR = 1046
|
|
786
849
|
ER_DUP_ENTRY = 1062
|
|
787
850
|
ER_SERVER_SHUTDOWN = 1053
|
|
788
851
|
ER_NOT_NULL_VIOLATION = 1048
|
|
@@ -803,6 +866,8 @@ module ActiveRecord
|
|
|
803
866
|
CR_SERVER_LOST = 2013
|
|
804
867
|
ER_QUERY_TIMEOUT = 3024
|
|
805
868
|
ER_FK_INCOMPATIBLE_COLUMNS = 3780
|
|
869
|
+
ER_CHECK_CONSTRAINT_VIOLATED = 3819
|
|
870
|
+
ER_CONSTRAINT_FAILED = 4025
|
|
806
871
|
ER_CLIENT_INTERACTION_TIMEOUT = 4031
|
|
807
872
|
|
|
808
873
|
def translate_exception(exception, message:, sql:, binds:)
|
|
@@ -813,7 +878,7 @@ module ActiveRecord
|
|
|
813
878
|
else
|
|
814
879
|
super
|
|
815
880
|
end
|
|
816
|
-
when ER_CONNECTION_KILLED, ER_SERVER_SHUTDOWN, CR_SERVER_GONE_ERROR, CR_SERVER_LOST, ER_CLIENT_INTERACTION_TIMEOUT
|
|
881
|
+
when ER_CONNECTION_KILLED, ER_SERVER_SHUTDOWN, CR_SERVER_GONE_ERROR, CR_SERVER_LOST, ER_CLIENT_INTERACTION_TIMEOUT, ER_NO_DB_ERROR
|
|
817
882
|
ConnectionFailed.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
818
883
|
when ER_DB_CREATE_EXISTS
|
|
819
884
|
DatabaseAlreadyExists.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
@@ -835,6 +900,8 @@ module ActiveRecord
|
|
|
835
900
|
RangeError.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
836
901
|
when ER_NOT_NULL_VIOLATION, ER_DO_NOT_HAVE_DEFAULT
|
|
837
902
|
NotNullViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
903
|
+
when ER_CHECK_CONSTRAINT_VIOLATED, ER_CONSTRAINT_FAILED
|
|
904
|
+
CheckViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
838
905
|
when ER_LOCK_DEADLOCK
|
|
839
906
|
Deadlocked.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
840
907
|
when ER_LOCK_WAIT_TIMEOUT
|
|
@@ -953,7 +1020,33 @@ module ActiveRecord
|
|
|
953
1020
|
end
|
|
954
1021
|
|
|
955
1022
|
def column_definitions(table_name) # :nodoc:
|
|
956
|
-
internal_exec_query("SHOW FULL FIELDS FROM #{quote_table_name(table_name)}", "SCHEMA")
|
|
1023
|
+
fields = internal_exec_query("SHOW FULL FIELDS FROM #{quote_table_name(table_name)}", "SCHEMA", allow_retry: true)
|
|
1024
|
+
|
|
1025
|
+
update_fields_for_mariadb(table_name, fields) if mariadb?
|
|
1026
|
+
|
|
1027
|
+
fields
|
|
1028
|
+
end
|
|
1029
|
+
|
|
1030
|
+
def update_fields_for_mariadb(table_name, fields)
|
|
1031
|
+
has_function_default_candidate = fields.any? do |field|
|
|
1032
|
+
default = field["Default"]
|
|
1033
|
+
default&.match?(/[a-zA-Z_]\w*\(/) && !/\ACURRENT_TIMESTAMP/i.match?(default)
|
|
1034
|
+
end
|
|
1035
|
+
|
|
1036
|
+
if has_function_default_candidate
|
|
1037
|
+
table_info = create_table_info(table_name)
|
|
1038
|
+
fields.each do |field|
|
|
1039
|
+
default = field["Default"]
|
|
1040
|
+
next unless default&.match?(/[a-zA-Z_]\w*\(/)
|
|
1041
|
+
next if /\ACURRENT_TIMESTAMP/i.match?(default)
|
|
1042
|
+
|
|
1043
|
+
field_name = field["Field"]
|
|
1044
|
+
match = table_info&.match(/`#{field_name}` .+ DEFAULT ('|\d+|[A-z]+)/)
|
|
1045
|
+
if match && match[1].match?(/\A[A-z]/)
|
|
1046
|
+
field["Extra"] = "DEFAULT_GENERATED"
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
end
|
|
957
1050
|
end
|
|
958
1051
|
|
|
959
1052
|
def create_table_info(table_name) # :nodoc:
|
|
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
|
7
7
|
class Column
|
|
8
8
|
include Deduplicable
|
|
9
9
|
|
|
10
|
-
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment
|
|
10
|
+
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment, :cast_type
|
|
11
11
|
|
|
12
12
|
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
|
|
13
13
|
|
|
@@ -17,8 +17,9 @@ module ActiveRecord
|
|
|
17
17
|
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
|
18
18
|
# +sql_type_metadata+ is various information about the type of the column
|
|
19
19
|
# +null+ determines if this column allows +NULL+ values.
|
|
20
|
-
def initialize(name, default, sql_type_metadata = nil, null = true, default_function = nil, collation: nil, comment: nil, **)
|
|
20
|
+
def initialize(name, cast_type, default, sql_type_metadata = nil, null = true, default_function = nil, collation: nil, comment: nil, **)
|
|
21
21
|
@name = name.freeze
|
|
22
|
+
@cast_type = cast_type
|
|
22
23
|
@sql_type_metadata = sql_type_metadata
|
|
23
24
|
@null = null
|
|
24
25
|
@default = default
|
|
@@ -27,6 +28,11 @@ module ActiveRecord
|
|
|
27
28
|
@comment = comment
|
|
28
29
|
end
|
|
29
30
|
|
|
31
|
+
def fetch_cast_type(connection) # :nodoc:
|
|
32
|
+
# TODO: Remove fetch_cast_type and the need for connection after we release 8.1.
|
|
33
|
+
@cast_type || connection.lookup_cast_type(sql_type)
|
|
34
|
+
end
|
|
35
|
+
|
|
30
36
|
def has_default?
|
|
31
37
|
!default.nil? || default_function
|
|
32
38
|
end
|
|
@@ -45,6 +51,7 @@ module ActiveRecord
|
|
|
45
51
|
|
|
46
52
|
def init_with(coder)
|
|
47
53
|
@name = coder["name"]
|
|
54
|
+
@cast_type = coder["cast_type"]
|
|
48
55
|
@sql_type_metadata = coder["sql_type_metadata"]
|
|
49
56
|
@null = coder["null"]
|
|
50
57
|
@default = coder["default"]
|
|
@@ -55,6 +62,7 @@ module ActiveRecord
|
|
|
55
62
|
|
|
56
63
|
def encode_with(coder)
|
|
57
64
|
coder["name"] = @name
|
|
65
|
+
coder["cast_type"] = @cast_type
|
|
58
66
|
coder["sql_type_metadata"] = @sql_type_metadata
|
|
59
67
|
coder["null"] = @null
|
|
60
68
|
coder["default"] = @default
|
|
@@ -75,6 +83,7 @@ module ActiveRecord
|
|
|
75
83
|
def ==(other)
|
|
76
84
|
other.is_a?(Column) &&
|
|
77
85
|
name == other.name &&
|
|
86
|
+
cast_type == other.cast_type &&
|
|
78
87
|
default == other.default &&
|
|
79
88
|
sql_type_metadata == other.sql_type_metadata &&
|
|
80
89
|
null == other.null &&
|
|
@@ -88,6 +97,7 @@ module ActiveRecord
|
|
|
88
97
|
Column.hash ^
|
|
89
98
|
name.hash ^
|
|
90
99
|
name.encoding.hash ^
|
|
100
|
+
cast_type.hash ^
|
|
91
101
|
default.hash ^
|
|
92
102
|
sql_type_metadata.hash ^
|
|
93
103
|
null.hash ^
|
|
@@ -104,7 +114,7 @@ module ActiveRecord
|
|
|
104
114
|
def deduplicated
|
|
105
115
|
@name = -name
|
|
106
116
|
@sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata
|
|
107
|
-
@default = -default if default
|
|
117
|
+
@default = -default if String === default
|
|
108
118
|
@default_function = -default_function if default_function
|
|
109
119
|
@collation = -collation if collation
|
|
110
120
|
@comment = -comment if comment
|
|
@@ -114,7 +124,7 @@ module ActiveRecord
|
|
|
114
124
|
|
|
115
125
|
class NullColumn < Column
|
|
116
126
|
def initialize(name, **)
|
|
117
|
-
super(name, nil)
|
|
127
|
+
super(name, nil, nil)
|
|
118
128
|
end
|
|
119
129
|
end
|
|
120
130
|
end
|
|
@@ -45,16 +45,16 @@ module ActiveRecord
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
def default_insert_value(column) # :nodoc:
|
|
49
|
+
super unless column.auto_increment?
|
|
50
|
+
end
|
|
51
|
+
|
|
48
52
|
private
|
|
49
53
|
# https://mariadb.com/kb/en/analyze-statement/
|
|
50
54
|
def analyze_without_explain?
|
|
51
55
|
mariadb? && database_version >= "10.1.0"
|
|
52
56
|
end
|
|
53
57
|
|
|
54
|
-
def default_insert_value(column)
|
|
55
|
-
super unless column.auto_increment?
|
|
56
|
-
end
|
|
57
|
-
|
|
58
58
|
def returning_column_values(result)
|
|
59
59
|
if supports_insert_returning?
|
|
60
60
|
result.rows.first
|
|
@@ -102,7 +102,13 @@ module ActiveRecord
|
|
|
102
102
|
else
|
|
103
103
|
value.getlocal
|
|
104
104
|
end
|
|
105
|
-
when
|
|
105
|
+
when Time
|
|
106
|
+
if default_timezone == :utc
|
|
107
|
+
value.utc? ? value : value.getutc
|
|
108
|
+
else
|
|
109
|
+
value.utc? ? value.getlocal : value
|
|
110
|
+
end
|
|
111
|
+
when Date
|
|
106
112
|
value
|
|
107
113
|
else
|
|
108
114
|
super
|
|
@@ -49,6 +49,8 @@ module ActiveRecord
|
|
|
49
49
|
sql << "USING #{o.using}" if o.using
|
|
50
50
|
sql << "ON #{quote_table_name(o.table)}" if create
|
|
51
51
|
sql << "(#{quoted_columns(o)})"
|
|
52
|
+
sql << "INVISIBLE" if o.disabled? && !mariadb?
|
|
53
|
+
sql << "IGNORED" if o.disabled? && mariadb?
|
|
52
54
|
|
|
53
55
|
add_sql_comment!(sql.join(" "), o.comment)
|
|
54
56
|
end
|
|
@@ -5,6 +5,7 @@ module ActiveRecord
|
|
|
5
5
|
module MySQL
|
|
6
6
|
module ColumnMethods
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
|
+
extend ConnectionAdapters::ColumnMethods::ClassMethods
|
|
8
9
|
|
|
9
10
|
##
|
|
10
11
|
# :method: blob
|
|
@@ -42,12 +43,26 @@ module ActiveRecord
|
|
|
42
43
|
# :method: unsigned_bigint
|
|
43
44
|
# :call-seq: unsigned_bigint(*names, **options)
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
define_column_methods :blob, :tinyblob, :mediumblob, :longblob,
|
|
47
|
+
:tinytext, :mediumtext, :longtext, :unsigned_integer, :unsigned_bigint
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# = Active Record MySQL Adapter \Index Definition
|
|
51
|
+
class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition # :nodoc:
|
|
52
|
+
attr_accessor :enabled
|
|
53
|
+
|
|
54
|
+
def initialize(*args, **kwargs)
|
|
55
|
+
@enabled = kwargs.key?(:enabled) ? kwargs.delete(:enabled) : true
|
|
56
|
+
super
|
|
57
|
+
end
|
|
49
58
|
|
|
50
|
-
|
|
59
|
+
def defined_for?(columns = nil, name: nil, unique: nil, valid: nil, include: nil, nulls_not_distinct: nil, enabled: nil, **options)
|
|
60
|
+
super(columns, name:, unique:, valid:, include:, nulls_not_distinct:, **options) &&
|
|
61
|
+
(enabled.nil? || self.enabled == enabled)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def disabled?
|
|
65
|
+
!@enabled
|
|
51
66
|
end
|
|
52
67
|
end
|
|
53
68
|
|
|
@@ -100,6 +115,28 @@ module ActiveRecord
|
|
|
100
115
|
# = Active Record MySQL Adapter \Table
|
|
101
116
|
class Table < ActiveRecord::ConnectionAdapters::Table
|
|
102
117
|
include ColumnMethods
|
|
118
|
+
|
|
119
|
+
# Enables an index to be used by query optimizers.
|
|
120
|
+
#
|
|
121
|
+
# t.enable_index(:email)
|
|
122
|
+
#
|
|
123
|
+
# Note: only supported by MySQL version 8.0.0 and greater, and MariaDB version 10.6.0 and greater.
|
|
124
|
+
#
|
|
125
|
+
# See {connection.enable_index}[rdoc-ref:SchemaStatements#enable_index]
|
|
126
|
+
def enable_index(index_name)
|
|
127
|
+
@base.enable_index(name, index_name)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Disables an index not to be used by query optimizers.
|
|
131
|
+
#
|
|
132
|
+
# t.disable_index(:email)
|
|
133
|
+
#
|
|
134
|
+
# Note: only supported by MySQL version 8.0.0 and greater, and MariaDB version 10.6.0 and greater.
|
|
135
|
+
#
|
|
136
|
+
# See {connection.disable_index}[rdoc-ref:SchemaStatements#disable_index]
|
|
137
|
+
def disable_index(index_name)
|
|
138
|
+
@base.disable_index(name, index_name)
|
|
139
|
+
end
|
|
103
140
|
end
|
|
104
141
|
end
|
|
105
142
|
end
|
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
|
21
21
|
index_using = mysql_index_type
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
index = [
|
|
25
25
|
row["Table"],
|
|
26
26
|
row["Key_name"],
|
|
27
27
|
row["Non_unique"].to_i == 0,
|
|
@@ -30,8 +30,14 @@ module ActiveRecord
|
|
|
30
30
|
orders: {},
|
|
31
31
|
type: index_type,
|
|
32
32
|
using: index_using,
|
|
33
|
-
comment: row["Index_comment"].presence
|
|
33
|
+
comment: row["Index_comment"].presence,
|
|
34
34
|
]
|
|
35
|
+
|
|
36
|
+
if supports_disabling_indexes?
|
|
37
|
+
index[-1][:enabled] = mariadb? ? row["Ignored"] == "NO" : row["Visible"] == "YES"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
indexes << index
|
|
35
41
|
end
|
|
36
42
|
|
|
37
43
|
if expression = row["Expression"]
|
|
@@ -63,8 +69,7 @@ module ActiveRecord
|
|
|
63
69
|
columns, order: orders, length: lengths
|
|
64
70
|
).values.join(", ")
|
|
65
71
|
end
|
|
66
|
-
|
|
67
|
-
IndexDefinition.new(*index, **options)
|
|
72
|
+
MySQL::IndexDefinition.new(*index, **options)
|
|
68
73
|
end
|
|
69
74
|
rescue StatementInvalid => e
|
|
70
75
|
if e.message.match?(/Table '.+' doesn't exist/)
|
|
@@ -74,6 +79,16 @@ module ActiveRecord
|
|
|
74
79
|
end
|
|
75
80
|
end
|
|
76
81
|
|
|
82
|
+
def create_index_definition(table_name, name, unique, columns, **options)
|
|
83
|
+
MySQL::IndexDefinition.new(table_name, name, unique, columns, **options)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def add_index_options(table_name, column_name, name: nil, if_not_exists: false, internal: false, **options) # :nodoc:
|
|
87
|
+
index, algorithm, if_not_exists = super
|
|
88
|
+
index.enabled = options[:enabled] unless options[:enabled].nil?
|
|
89
|
+
[index, algorithm, if_not_exists]
|
|
90
|
+
end
|
|
91
|
+
|
|
77
92
|
def remove_column(table_name, column_name, type = nil, **options)
|
|
78
93
|
if foreign_key_exists?(table_name, column: column_name)
|
|
79
94
|
remove_foreign_key(table_name, column: column_name)
|
|
@@ -85,6 +100,13 @@ module ActiveRecord
|
|
|
85
100
|
super
|
|
86
101
|
end
|
|
87
102
|
|
|
103
|
+
def remove_foreign_key(from_table, to_table = nil, **options)
|
|
104
|
+
# RESTRICT is by default in MySQL.
|
|
105
|
+
options.delete(:on_update) if options[:on_update] == :restrict
|
|
106
|
+
options.delete(:on_delete) if options[:on_delete] == :restrict
|
|
107
|
+
super
|
|
108
|
+
end
|
|
109
|
+
|
|
88
110
|
def internal_string_options_for_primary_key
|
|
89
111
|
super.tap do |options|
|
|
90
112
|
if !row_format_dynamic_by_default? && CHARSETS_OF_4BYTES_MAXLEN.include?(charset)
|
|
@@ -166,21 +188,7 @@ module ActiveRecord
|
|
|
166
188
|
MySQL::TableDefinition.new(self, name, **options)
|
|
167
189
|
end
|
|
168
190
|
|
|
169
|
-
def default_type(table_name, field_name)
|
|
170
|
-
match = create_table_info(table_name)&.match(/`#{field_name}` (.+) DEFAULT ('|\d+|[A-z]+)/)
|
|
171
|
-
default_pre = match[2] if match
|
|
172
|
-
|
|
173
|
-
if default_pre == "'"
|
|
174
|
-
:string
|
|
175
|
-
elsif default_pre&.match?(/^\d+$/)
|
|
176
|
-
:integer
|
|
177
|
-
elsif default_pre&.match?(/^[A-z]+$/)
|
|
178
|
-
:function
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
|
|
182
191
|
def new_column_from_field(table_name, field, _definitions)
|
|
183
|
-
field_name = field.fetch("Field")
|
|
184
192
|
type_metadata = fetch_type_metadata(field["Type"], field["Extra"])
|
|
185
193
|
default, default_function = field["Default"], nil
|
|
186
194
|
|
|
@@ -188,20 +196,21 @@ module ActiveRecord
|
|
|
188
196
|
default = "#{default} ON UPDATE #{default}" if /on update CURRENT_TIMESTAMP/i.match?(field["Extra"])
|
|
189
197
|
default, default_function = nil, default
|
|
190
198
|
elsif type_metadata.extra == "DEFAULT_GENERATED"
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
199
|
+
if mariadb?
|
|
200
|
+
default, default_function = nil, default
|
|
201
|
+
else
|
|
202
|
+
default = "(#{default})" unless default.start_with?("(")
|
|
203
|
+
default = default.gsub("\\'", "'")
|
|
204
|
+
default, default_function = nil, default
|
|
205
|
+
end
|
|
194
206
|
elsif type_metadata.type == :text && default&.start_with?("'")
|
|
195
207
|
# strip and unescape quotes
|
|
196
208
|
default = default[1...-1].gsub("\\'", "'")
|
|
197
|
-
elsif default&.match?(/\A\d/)
|
|
198
|
-
# Its a number so we can skip the query to check if it is a function
|
|
199
|
-
elsif default && default_type(table_name, field_name) == :function
|
|
200
|
-
default, default_function = nil, default
|
|
201
209
|
end
|
|
202
210
|
|
|
203
211
|
MySQL::Column.new(
|
|
204
212
|
field["Field"],
|
|
213
|
+
lookup_cast_type(type_metadata.sql_type),
|
|
205
214
|
default,
|
|
206
215
|
type_metadata,
|
|
207
216
|
field["Null"] == "YES",
|
|
@@ -226,6 +235,12 @@ module ActiveRecord
|
|
|
226
235
|
end
|
|
227
236
|
end
|
|
228
237
|
|
|
238
|
+
def valid_index_options
|
|
239
|
+
index_options = super
|
|
240
|
+
index_options << :enabled if supports_disabling_indexes?
|
|
241
|
+
index_options
|
|
242
|
+
end
|
|
243
|
+
|
|
229
244
|
def add_options_for_index_columns(quoted_columns, **options)
|
|
230
245
|
quoted_columns = add_index_length(quoted_columns, **options)
|
|
231
246
|
super
|