activerecord 6.0.1 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +843 -626
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record/aggregations.rb +1 -2
- data/lib/active_record/association_relation.rb +18 -17
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +49 -37
- data/lib/active_record/associations/association_scope.rb +17 -15
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +9 -3
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +25 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +36 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +73 -42
- data/lib/active_record/associations/preloader/association.rb +51 -25
- data/lib/active_record/associations/preloader/through_association.rb +2 -2
- data/lib/active_record/associations/preloader.rb +12 -7
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +115 -12
- data/lib/active_record/attribute_assignment.rb +10 -9
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +32 -8
- data/lib/active_record/autosave_association.rb +56 -41
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +190 -136
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +82 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -8
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +263 -107
- data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
- data/lib/active_record/connection_adapters/abstract_adapter.rb +60 -73
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +136 -111
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +28 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -56
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +77 -57
- data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +36 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -57
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +210 -87
- data/lib/active_record/core.rb +229 -65
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -41
- data/lib/active_record/database_configurations.rb +124 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +40 -16
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +54 -11
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +38 -9
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +16 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +22 -17
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +27 -9
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -2
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +70 -20
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +114 -84
- data/lib/active_record/model_schema.rb +117 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/databases.rake +267 -93
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/calculations.rb +102 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +45 -16
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +55 -35
- data/lib/active_record/relation/query_methods.rb +335 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +104 -58
- data/lib/active_record/relation.rb +108 -68
- data/lib/active_record/result.rb +41 -34
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +3 -3
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -36
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +38 -16
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +21 -70
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +8 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +17 -24
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -9
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +6 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +26 -26
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
module MySQL
|
6
6
|
module DatabaseStatements
|
7
7
|
# Returns an ActiveRecord::Result instance.
|
8
|
-
def select_all(
|
8
|
+
def select_all(*, **) # :nodoc:
|
9
9
|
result = if ExplainRegistry.collect? && prepared_statements
|
10
10
|
unprepared_statement { super }
|
11
11
|
else
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
end
|
21
21
|
|
22
22
|
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
23
|
-
:
|
23
|
+
:desc, :describe, :set, :show, :use
|
24
24
|
) # :nodoc:
|
25
25
|
private_constant :READ_QUERY
|
26
26
|
|
@@ -28,6 +28,15 @@ module ActiveRecord
|
|
28
28
|
!READ_QUERY.match?(sql)
|
29
29
|
end
|
30
30
|
|
31
|
+
def explain(arel, binds = [])
|
32
|
+
sql = "EXPLAIN #{to_sql(arel, binds)}"
|
33
|
+
start = Concurrent.monotonic_time
|
34
|
+
result = exec_query(sql, "EXPLAIN", binds)
|
35
|
+
elapsed = Concurrent.monotonic_time - start
|
36
|
+
|
37
|
+
MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
|
38
|
+
end
|
39
|
+
|
31
40
|
# Executes the SQL statement in the context of this connection.
|
32
41
|
def execute(sql, name = nil)
|
33
42
|
if preventing_writes? && write_query?(sql)
|
@@ -45,17 +54,17 @@ module ActiveRecord
|
|
45
54
|
if without_prepared_statement?(binds)
|
46
55
|
execute_and_free(sql, name) do |result|
|
47
56
|
if result
|
48
|
-
|
57
|
+
build_result(columns: result.fields, rows: result.to_a)
|
49
58
|
else
|
50
|
-
|
59
|
+
build_result(columns: [], rows: [])
|
51
60
|
end
|
52
61
|
end
|
53
62
|
else
|
54
63
|
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
|
55
64
|
if result
|
56
|
-
|
65
|
+
build_result(columns: result.fields, rows: result.to_a)
|
57
66
|
else
|
58
|
-
|
67
|
+
build_result(columns: [], rows: [])
|
59
68
|
end
|
60
69
|
end
|
61
70
|
end
|
@@ -73,8 +82,10 @@ module ActiveRecord
|
|
73
82
|
alias :exec_update :exec_delete
|
74
83
|
|
75
84
|
private
|
76
|
-
def execute_batch(
|
77
|
-
|
85
|
+
def execute_batch(statements, name = nil)
|
86
|
+
combine_multi_statements(statements).each do |statement|
|
87
|
+
execute(statement, name)
|
88
|
+
end
|
78
89
|
@connection.abandon_results!
|
79
90
|
end
|
80
91
|
|
@@ -86,47 +97,27 @@ module ActiveRecord
|
|
86
97
|
@connection.last_id
|
87
98
|
end
|
88
99
|
|
89
|
-
def
|
90
|
-
@
|
91
|
-
end
|
92
|
-
|
93
|
-
def build_truncate_statements(*table_names)
|
94
|
-
if table_names.size == 1
|
95
|
-
super.first
|
96
|
-
else
|
97
|
-
super
|
98
|
-
end
|
99
|
-
end
|
100
|
+
def multi_statements_enabled?
|
101
|
+
flags = @config[:flags]
|
100
102
|
|
101
|
-
def multi_statements_enabled?(flags)
|
102
103
|
if flags.is_a?(Array)
|
103
104
|
flags.include?("MULTI_STATEMENTS")
|
104
105
|
else
|
105
|
-
(
|
106
|
+
flags.anybits?(Mysql2::Client::MULTI_STATEMENTS)
|
106
107
|
end
|
107
108
|
end
|
108
109
|
|
109
110
|
def with_multi_statements
|
110
|
-
|
111
|
+
multi_statements_was = multi_statements_enabled?
|
111
112
|
|
112
|
-
unless
|
113
|
-
|
114
|
-
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
115
|
-
else
|
116
|
-
@config[:flags] = Mysql2::Client::MULTI_STATEMENTS
|
117
|
-
reconnect!
|
118
|
-
end
|
113
|
+
unless multi_statements_was
|
114
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
119
115
|
end
|
120
116
|
|
121
117
|
yield
|
122
118
|
ensure
|
123
|
-
unless
|
124
|
-
|
125
|
-
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
126
|
-
else
|
127
|
-
@config[:flags] = previous_flags
|
128
|
-
reconnect!
|
129
|
-
end
|
119
|
+
unless multi_statements_was
|
120
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
130
121
|
end
|
131
122
|
end
|
132
123
|
|
@@ -163,6 +154,7 @@ module ActiveRecord
|
|
163
154
|
end
|
164
155
|
|
165
156
|
materialize_transactions
|
157
|
+
mark_transaction_written_if_write(sql)
|
166
158
|
|
167
159
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
168
160
|
# made since we established the connection
|
@@ -37,7 +37,6 @@ module ActiveRecord
|
|
37
37
|
end
|
38
38
|
|
39
39
|
private
|
40
|
-
|
41
40
|
def compute_column_widths(result)
|
42
41
|
[].tap do |widths|
|
43
42
|
result.columns.each_with_index do |column, i|
|
@@ -57,7 +56,7 @@ module ActiveRecord
|
|
57
56
|
items.each_with_index do |item, i|
|
58
57
|
item = "NULL" if item.nil?
|
59
58
|
justifier = item.is_a?(Numeric) ? "rjust" : "ljust"
|
60
|
-
cells << item.to_s.
|
59
|
+
cells << item.to_s.public_send(justifier, widths[i])
|
61
60
|
end
|
62
61
|
"| " + cells.join(" | ") + " |"
|
63
62
|
end
|
@@ -3,15 +3,18 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module MySQL
|
6
|
-
class SchemaCreation <
|
6
|
+
class SchemaCreation < SchemaCreation # :nodoc:
|
7
7
|
delegate :add_sql_comment!, :mariadb?, to: :@conn, private: true
|
8
8
|
|
9
9
|
private
|
10
|
-
|
11
10
|
def visit_DropForeignKey(name)
|
12
11
|
"DROP FOREIGN KEY #{name}"
|
13
12
|
end
|
14
13
|
|
14
|
+
def visit_DropCheckConstraint(name)
|
15
|
+
"DROP #{mariadb? ? 'CONSTRAINT' : 'CHECK'} #{name}"
|
16
|
+
end
|
17
|
+
|
15
18
|
def visit_AddColumnDefinition(o)
|
16
19
|
add_column_position!(super, column_options(o.column))
|
17
20
|
end
|
@@ -21,15 +24,37 @@ module ActiveRecord
|
|
21
24
|
add_column_position!(change_column_sql, column_options(o.column))
|
22
25
|
end
|
23
26
|
|
24
|
-
def
|
25
|
-
|
27
|
+
def visit_CreateIndexDefinition(o)
|
28
|
+
sql = visit_IndexDefinition(o.index, true)
|
29
|
+
sql << " #{o.algorithm}" if o.algorithm
|
30
|
+
sql
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_IndexDefinition(o, create = false)
|
34
|
+
index_type = o.type&.to_s&.upcase || o.unique && "UNIQUE"
|
35
|
+
|
36
|
+
sql = create ? ["CREATE"] : []
|
37
|
+
sql << index_type if index_type
|
38
|
+
sql << "INDEX"
|
39
|
+
sql << quote_column_name(o.name)
|
40
|
+
sql << "USING #{o.using}" if o.using
|
41
|
+
sql << "ON #{quote_table_name(o.table)}" if create
|
42
|
+
sql << "(#{quoted_columns(o)})"
|
43
|
+
|
44
|
+
add_sql_comment!(sql.join(" "), o.comment)
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_table_options!(create_sql, o)
|
48
|
+
create_sql << " DEFAULT CHARSET=#{o.charset}" if o.charset
|
49
|
+
create_sql << " COLLATE=#{o.collation}" if o.collation
|
50
|
+
add_sql_comment!(super, o.comment)
|
26
51
|
end
|
27
52
|
|
28
53
|
def add_column_options!(sql, options)
|
29
54
|
# By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values,
|
30
55
|
# and assigning NULL assigns the current timestamp. To permit a TIMESTAMP
|
31
56
|
# column to contain NULL, explicitly declare it with the NULL attribute.
|
32
|
-
# See https://dev.mysql.com/doc/refman/
|
57
|
+
# See https://dev.mysql.com/doc/refman/en/timestamp-initialization.html
|
33
58
|
if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key]
|
34
59
|
sql << " NULL" unless options[:null] == false || options_include_default?(options)
|
35
60
|
end
|
@@ -63,8 +88,8 @@ module ActiveRecord
|
|
63
88
|
end
|
64
89
|
|
65
90
|
def index_in_create(table_name, column_name, options)
|
66
|
-
|
67
|
-
|
91
|
+
index, _ = @conn.add_index_options(table_name, column_name, **options)
|
92
|
+
accept(index)
|
68
93
|
end
|
69
94
|
end
|
70
95
|
end
|
@@ -60,6 +60,14 @@ module ActiveRecord
|
|
60
60
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
61
61
|
include ColumnMethods
|
62
62
|
|
63
|
+
attr_reader :charset, :collation
|
64
|
+
|
65
|
+
def initialize(conn, name, charset: nil, collation: nil, **)
|
66
|
+
super
|
67
|
+
@charset = charset
|
68
|
+
@collation = collation
|
69
|
+
end
|
70
|
+
|
63
71
|
def new_column_definition(name, type, **options) # :nodoc:
|
64
72
|
case type
|
65
73
|
when :virtual
|
@@ -49,7 +49,7 @@ module ActiveRecord
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def schema_limit(column)
|
52
|
-
super unless /\A(?:
|
52
|
+
super unless /\A(?:tiny|medium|long)?(?:text|blob)\b/.match?(column.sql_type)
|
53
53
|
end
|
54
54
|
|
55
55
|
def schema_precision(column)
|
@@ -51,26 +51,26 @@ module ActiveRecord
|
|
51
51
|
end
|
52
52
|
|
53
53
|
indexes.map do |index|
|
54
|
-
options = index.
|
54
|
+
options = index.pop
|
55
55
|
|
56
56
|
if expressions = options.delete(:expressions)
|
57
57
|
orders = options.delete(:orders)
|
58
58
|
lengths = options.delete(:lengths)
|
59
59
|
|
60
|
-
columns = index[-
|
60
|
+
columns = index[-1].map { |name|
|
61
61
|
[ name.to_sym, expressions[name] || +quote_column_name(name) ]
|
62
62
|
}.to_h
|
63
63
|
|
64
|
-
index[-
|
64
|
+
index[-1] = add_options_for_index_columns(
|
65
65
|
columns, order: orders, length: lengths
|
66
66
|
).values.join(", ")
|
67
67
|
end
|
68
68
|
|
69
|
-
IndexDefinition.new(*index)
|
69
|
+
IndexDefinition.new(*index, **options)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
def remove_column(table_name, column_name, type = nil, options
|
73
|
+
def remove_column(table_name, column_name, type = nil, **options)
|
74
74
|
if foreign_key_exists?(table_name, column: column_name)
|
75
75
|
remove_foreign_key(table_name, column: column_name)
|
76
76
|
end
|
@@ -122,7 +122,7 @@ module ActiveRecord
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def table_alias_length
|
125
|
-
256 # https://dev.mysql.com/doc/refman/
|
125
|
+
256 # https://dev.mysql.com/doc/refman/en/identifiers.html
|
126
126
|
end
|
127
127
|
|
128
128
|
private
|
@@ -154,8 +154,8 @@ module ActiveRecord
|
|
154
154
|
MySQL::SchemaCreation.new(self)
|
155
155
|
end
|
156
156
|
|
157
|
-
def create_table_definition(
|
158
|
-
MySQL::TableDefinition.new(self,
|
157
|
+
def create_table_definition(name, **options)
|
158
|
+
MySQL::TableDefinition.new(self, name, **options)
|
159
159
|
end
|
160
160
|
|
161
161
|
def new_column_from_field(table_name, field)
|
@@ -196,17 +196,21 @@ module ActiveRecord
|
|
196
196
|
end
|
197
197
|
|
198
198
|
def add_options_for_index_columns(quoted_columns, **options)
|
199
|
-
quoted_columns = add_index_length(quoted_columns, options)
|
199
|
+
quoted_columns = add_index_length(quoted_columns, **options)
|
200
200
|
super
|
201
201
|
end
|
202
202
|
|
203
203
|
def data_source_sql(name = nil, type: nil)
|
204
204
|
scope = quoted_scope(name, type: type)
|
205
205
|
|
206
|
-
sql = +"SELECT table_name FROM information_schema.tables"
|
207
|
-
sql << " WHERE table_schema = #{scope[:schema]}"
|
208
|
-
|
209
|
-
|
206
|
+
sql = +"SELECT table_name FROM (SELECT * FROM information_schema.tables "
|
207
|
+
sql << " WHERE table_schema = #{scope[:schema]}) _subquery"
|
208
|
+
if scope[:type] || scope[:name]
|
209
|
+
conditions = []
|
210
|
+
conditions << "_subquery.table_type = #{scope[:type]}" if scope[:type]
|
211
|
+
conditions << "_subquery.table_name = #{scope[:name]}" if scope[:name]
|
212
|
+
sql << " WHERE #{conditions.join(" AND ")}"
|
213
|
+
end
|
210
214
|
sql
|
211
215
|
end
|
212
216
|
|
@@ -6,9 +6,11 @@ module ActiveRecord
|
|
6
6
|
class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc:
|
7
7
|
undef to_yaml if method_defined?(:to_yaml)
|
8
8
|
|
9
|
+
include Deduplicable
|
10
|
+
|
9
11
|
attr_reader :extra
|
10
12
|
|
11
|
-
def initialize(type_metadata, extra:
|
13
|
+
def initialize(type_metadata, extra: nil)
|
12
14
|
super(type_metadata)
|
13
15
|
@extra = extra
|
14
16
|
end
|
@@ -25,6 +27,13 @@ module ActiveRecord
|
|
25
27
|
__getobj__.hash ^
|
26
28
|
extra.hash
|
27
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def deduplicated
|
33
|
+
__setobj__(__getobj__.deduplicate)
|
34
|
+
@extra = -extra if extra
|
35
|
+
super
|
36
|
+
end
|
28
37
|
end
|
29
38
|
end
|
30
39
|
end
|
@@ -3,13 +3,11 @@
|
|
3
3
|
require "active_record/connection_adapters/abstract_mysql_adapter"
|
4
4
|
require "active_record/connection_adapters/mysql/database_statements"
|
5
5
|
|
6
|
-
gem "mysql2", "
|
6
|
+
gem "mysql2", "~> 0.5"
|
7
7
|
require "mysql2"
|
8
8
|
|
9
9
|
module ActiveRecord
|
10
10
|
module ConnectionHandling # :nodoc:
|
11
|
-
ER_BAD_DB_ERROR = 1049
|
12
|
-
|
13
11
|
# Establishes a connection to the database that's used by all Active Record objects.
|
14
12
|
def mysql2_connection(config)
|
15
13
|
config = config.symbolize_keys
|
@@ -21,23 +19,34 @@ module ActiveRecord
|
|
21
19
|
config[:flags] |= Mysql2::Client::FOUND_ROWS
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
raise
|
31
|
-
end
|
22
|
+
ConnectionAdapters::Mysql2Adapter.new(
|
23
|
+
ConnectionAdapters::Mysql2Adapter.new_client(config),
|
24
|
+
logger,
|
25
|
+
nil,
|
26
|
+
config,
|
27
|
+
)
|
32
28
|
end
|
33
29
|
end
|
34
30
|
|
35
31
|
module ConnectionAdapters
|
36
32
|
class Mysql2Adapter < AbstractMysqlAdapter
|
33
|
+
ER_BAD_DB_ERROR = 1049
|
37
34
|
ADAPTER_NAME = "Mysql2"
|
38
35
|
|
39
36
|
include MySQL::DatabaseStatements
|
40
37
|
|
38
|
+
class << self
|
39
|
+
def new_client(config)
|
40
|
+
Mysql2::Client.new(config)
|
41
|
+
rescue Mysql2::Error => error
|
42
|
+
if error.error_number == ConnectionAdapters::Mysql2Adapter::ER_BAD_DB_ERROR
|
43
|
+
raise ActiveRecord::NoDatabaseError
|
44
|
+
else
|
45
|
+
raise ActiveRecord::ConnectionNotEstablished, error.message
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
41
50
|
def initialize(connection, logger, connection_options, config)
|
42
51
|
superclass_config = config.reverse_merge(prepared_statements: false)
|
43
52
|
super(connection, logger, connection_options, superclass_config)
|
@@ -92,6 +101,8 @@ module ActiveRecord
|
|
92
101
|
|
93
102
|
def quote_string(string)
|
94
103
|
@connection.escape(string)
|
104
|
+
rescue Mysql2::Error => error
|
105
|
+
raise translate_exception(error, message: error.message, sql: "<escape>", binds: [])
|
95
106
|
end
|
96
107
|
|
97
108
|
#--
|
@@ -123,9 +134,8 @@ module ActiveRecord
|
|
123
134
|
end
|
124
135
|
|
125
136
|
private
|
126
|
-
|
127
137
|
def connect
|
128
|
-
@connection =
|
138
|
+
@connection = self.class.new_client(@config)
|
129
139
|
configure_connection
|
130
140
|
end
|
131
141
|
|
@@ -141,6 +151,14 @@ module ActiveRecord
|
|
141
151
|
def get_full_version
|
142
152
|
@connection.server_info[:version]
|
143
153
|
end
|
154
|
+
|
155
|
+
def translate_exception(exception, message:, sql:, binds:)
|
156
|
+
if exception.is_a?(Mysql2::Error::TimeoutError) && !exception.error_number
|
157
|
+
ActiveRecord::AdapterTimeout.new(message, sql: sql, binds: binds)
|
158
|
+
else
|
159
|
+
super
|
160
|
+
end
|
161
|
+
end
|
144
162
|
end
|
145
163
|
end
|
146
164
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
class PoolConfig # :nodoc:
|
6
|
+
include Mutex_m
|
7
|
+
|
8
|
+
attr_reader :db_config, :connection_specification_name
|
9
|
+
attr_accessor :schema_cache
|
10
|
+
|
11
|
+
INSTANCES = ObjectSpace::WeakMap.new
|
12
|
+
private_constant :INSTANCES
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def discard_pools!
|
16
|
+
INSTANCES.each_key(&:discard_pool!)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(connection_specification_name, db_config)
|
21
|
+
super()
|
22
|
+
@connection_specification_name = connection_specification_name
|
23
|
+
@db_config = db_config
|
24
|
+
@pool = nil
|
25
|
+
INSTANCES[self] = self
|
26
|
+
end
|
27
|
+
|
28
|
+
def disconnect!
|
29
|
+
ActiveSupport::ForkTracker.check!
|
30
|
+
|
31
|
+
return unless @pool
|
32
|
+
|
33
|
+
synchronize do
|
34
|
+
return unless @pool
|
35
|
+
|
36
|
+
@pool.automatic_reconnect = false
|
37
|
+
@pool.disconnect!
|
38
|
+
end
|
39
|
+
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def pool
|
44
|
+
ActiveSupport::ForkTracker.check!
|
45
|
+
|
46
|
+
@pool || synchronize { @pool ||= ConnectionAdapters::ConnectionPool.new(self) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def discard_pool!
|
50
|
+
return unless @pool
|
51
|
+
|
52
|
+
synchronize do
|
53
|
+
return unless @pool
|
54
|
+
|
55
|
+
@pool.discard!
|
56
|
+
@pool = nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
ActiveSupport::ForkTracker.after_fork { ActiveRecord::ConnectionAdapters::PoolConfig.discard_pools! }
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
class PoolManager # :nodoc:
|
6
|
+
def initialize
|
7
|
+
@name_to_role_mapping = Hash.new { |h, k| h[k] = {} }
|
8
|
+
end
|
9
|
+
|
10
|
+
def shard_names
|
11
|
+
@name_to_role_mapping.values.flat_map { |shard_map| shard_map.keys }
|
12
|
+
end
|
13
|
+
|
14
|
+
def role_names
|
15
|
+
@name_to_role_mapping.keys
|
16
|
+
end
|
17
|
+
|
18
|
+
def pool_configs(role = nil)
|
19
|
+
if role
|
20
|
+
@name_to_role_mapping[role].values
|
21
|
+
else
|
22
|
+
@name_to_role_mapping.flat_map { |_, shard_map| shard_map.values }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove_role(role)
|
27
|
+
@name_to_role_mapping.delete(role)
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_pool_config(role, shard)
|
31
|
+
@name_to_role_mapping[role].delete(shard)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_pool_config(role, shard)
|
35
|
+
@name_to_role_mapping[role][shard]
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_pool_config(role, shard, pool_config)
|
39
|
+
@name_to_role_mapping[role][shard] = pool_config
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -21,7 +21,30 @@ module ActiveRecord
|
|
21
21
|
alias :array? :array
|
22
22
|
|
23
23
|
def sql_type
|
24
|
-
super.
|
24
|
+
super.delete_suffix("[]")
|
25
|
+
end
|
26
|
+
|
27
|
+
def init_with(coder)
|
28
|
+
@serial = coder["serial"]
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def encode_with(coder)
|
33
|
+
coder["serial"] = @serial
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def ==(other)
|
38
|
+
other.is_a?(Column) &&
|
39
|
+
super &&
|
40
|
+
serial? == other.serial?
|
41
|
+
end
|
42
|
+
alias :eql? :==
|
43
|
+
|
44
|
+
def hash
|
45
|
+
Column.hash ^
|
46
|
+
super.hash ^
|
47
|
+
serial?.hash
|
25
48
|
end
|
26
49
|
end
|
27
50
|
end
|