activerecord 6.0.3.4 → 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 +799 -713
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/active_record.rb +7 -14
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +22 -14
- data/lib/active_record/associations.rb +114 -11
- data/lib/active_record/associations/alias_tracker.rb +19 -15
- data/lib/active_record/associations/association.rb +44 -28
- 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 -1
- 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 +19 -6
- data/lib/active_record/associations/collection_proxy.rb +13 -5
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -2
- 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.rb +72 -50
- 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/preloader.rb +11 -5
- 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/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +10 -8
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
- data/lib/active_record/attribute_methods/dirty.rb +1 -11
- data/lib/active_record/attribute_methods/primary_key.rb +6 -2
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -11
- data/lib/active_record/attribute_methods/serialization.rb +11 -5
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
- data/lib/active_record/attribute_methods/write.rb +12 -20
- data/lib/active_record/attributes.rb +32 -7
- data/lib/active_record/autosave_association.rb +57 -40
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +152 -22
- data/lib/active_record/coders/yaml_column.rb +1 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +191 -134
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
- 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 +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +112 -27
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +80 -32
- data/lib/active_record/connection_adapters/abstract_adapter.rb +54 -71
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +129 -88
- 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/database_statements.rb +23 -25
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
- 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 +11 -7
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
- 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 +13 -54
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- 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/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
- 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 +31 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +37 -4
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -50
- data/lib/active_record/connection_handling.rb +210 -71
- data/lib/active_record/core.rb +229 -63
- data/lib/active_record/database_configurations.rb +124 -85
- 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 -40
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/enum.rb +40 -16
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -4
- 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 -2
- data/lib/active_record/fixtures.rb +54 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +40 -18
- data/lib/active_record/insert_all.rb +35 -6
- 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 -16
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +26 -8
- data/lib/active_record/middleware/database_selector.rb +4 -1
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/migration.rb +113 -83
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +67 -17
- data/lib/active_record/model_schema.rb +117 -13
- data/lib/active_record/nested_attributes.rb +2 -3
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +50 -45
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +11 -6
- data/lib/active_record/railtie.rb +64 -44
- data/lib/active_record/railties/databases.rake +266 -95
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +71 -57
- data/lib/active_record/relation.rb +96 -67
- data/lib/active_record/relation/batches.rb +38 -31
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/calculations.rb +101 -44
- data/lib/active_record/relation/delegation.rb +2 -1
- data/lib/active_record/relation/finder_methods.rb +45 -15
- data/lib/active_record/relation/from_clause.rb +1 -1
- data/lib/active_record/relation/merger.rb +27 -25
- data/lib/active_record/relation/predicate_builder.rb +57 -33
- 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/query_methods.rb +330 -195
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +104 -57
- data/lib/active_record/result.rb +41 -33
- 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/named.rb +6 -17
- 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 +2 -2
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -51
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +37 -16
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/touch_later.rb +21 -21
- data/lib/active_record/transactions.rb +15 -64
- data/lib/active_record/type.rb +8 -1
- data/lib/active_record/type/serialized.rb +6 -2
- data/lib/active_record/type/time.rb +10 -0
- 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.rb +1 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/arel.rb +5 -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.rb +3 -1
- 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/predications.rb +12 -18
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel/visitors/dot.rb +14 -2
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -4
- data/lib/arel/visitors/to_sql.rb +89 -78
- data/lib/rails/generators/active_record/migration.rb +6 -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 +3 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +27 -28
- data/lib/active_record/advisory_lock_base.rb +0 -18
- data/lib/active_record/attribute_decorators.rb +0 -88
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
- 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 -203
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -156
- data/lib/arel/visitors/oracle.rb +0 -158
- data/lib/arel/visitors/oracle12.rb +0 -65
- data/lib/arel/visitors/where_sql.rb +0 -22
@@ -5,6 +5,8 @@ module ActiveRecord
|
|
5
5
|
module ConnectionAdapters
|
6
6
|
# An abstract definition of a column in a table.
|
7
7
|
class Column
|
8
|
+
include Deduplicable
|
9
|
+
|
8
10
|
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment
|
9
11
|
|
10
12
|
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
|
@@ -76,6 +78,7 @@ module ActiveRecord
|
|
76
78
|
def hash
|
77
79
|
Column.hash ^
|
78
80
|
name.hash ^
|
81
|
+
name.encoding.hash ^
|
79
82
|
default.hash ^
|
80
83
|
sql_type_metadata.hash ^
|
81
84
|
null.hash ^
|
@@ -83,10 +86,21 @@ module ActiveRecord
|
|
83
86
|
collation.hash ^
|
84
87
|
comment.hash
|
85
88
|
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def deduplicated
|
92
|
+
@name = -name
|
93
|
+
@sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata
|
94
|
+
@default = -default if default
|
95
|
+
@default_function = -default_function if default_function
|
96
|
+
@collation = -collation if collation
|
97
|
+
@comment = -comment if comment
|
98
|
+
super
|
99
|
+
end
|
86
100
|
end
|
87
101
|
|
88
102
|
class NullColumn < Column
|
89
|
-
def initialize(name)
|
103
|
+
def initialize(name, **)
|
90
104
|
super(name, nil)
|
91
105
|
end
|
92
106
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters # :nodoc:
|
5
|
+
module Deduplicable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def registry
|
10
|
+
@registry ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def new(*, **)
|
14
|
+
super.deduplicate
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def deduplicate
|
19
|
+
self.class.registry[self] ||= deduplicated
|
20
|
+
end
|
21
|
+
alias :-@ :deduplicate
|
22
|
+
|
23
|
+
private
|
24
|
+
def deduplicated
|
25
|
+
freeze
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
class LegacyPoolManager # :nodoc:
|
6
|
+
def initialize
|
7
|
+
@name_to_pool_config = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def shard_names
|
11
|
+
@name_to_pool_config.keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def pool_configs(_ = nil)
|
15
|
+
@name_to_pool_config.values
|
16
|
+
end
|
17
|
+
|
18
|
+
def remove_pool_config(_, shard)
|
19
|
+
@name_to_pool_config.delete(shard)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_pool_config(_, shard)
|
23
|
+
@name_to_pool_config[shard]
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_pool_config(_, shard, pool_config)
|
27
|
+
@name_to_pool_config[shard] = pool_config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -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
|
@@ -88,39 +97,27 @@ module ActiveRecord
|
|
88
97
|
@connection.last_id
|
89
98
|
end
|
90
99
|
|
91
|
-
def
|
92
|
-
@
|
93
|
-
end
|
100
|
+
def multi_statements_enabled?
|
101
|
+
flags = @config[:flags]
|
94
102
|
|
95
|
-
def multi_statements_enabled?(flags)
|
96
103
|
if flags.is_a?(Array)
|
97
104
|
flags.include?("MULTI_STATEMENTS")
|
98
105
|
else
|
99
|
-
(
|
106
|
+
flags.anybits?(Mysql2::Client::MULTI_STATEMENTS)
|
100
107
|
end
|
101
108
|
end
|
102
109
|
|
103
110
|
def with_multi_statements
|
104
|
-
|
111
|
+
multi_statements_was = multi_statements_enabled?
|
105
112
|
|
106
|
-
unless
|
107
|
-
|
108
|
-
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
109
|
-
else
|
110
|
-
@config[:flags] = Mysql2::Client::MULTI_STATEMENTS
|
111
|
-
reconnect!
|
112
|
-
end
|
113
|
+
unless multi_statements_was
|
114
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
113
115
|
end
|
114
116
|
|
115
117
|
yield
|
116
118
|
ensure
|
117
|
-
unless
|
118
|
-
|
119
|
-
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
120
|
-
else
|
121
|
-
@config[:flags] = previous_flags
|
122
|
-
reconnect!
|
123
|
-
end
|
119
|
+
unless multi_statements_was
|
120
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
124
121
|
end
|
125
122
|
end
|
126
123
|
|
@@ -157,6 +154,7 @@ module ActiveRecord
|
|
157
154
|
end
|
158
155
|
|
159
156
|
materialize_transactions
|
157
|
+
mark_transaction_written_if_write(sql)
|
160
158
|
|
161
159
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
162
160
|
# made since we established the connection
|
@@ -56,7 +56,7 @@ module ActiveRecord
|
|
56
56
|
items.each_with_index do |item, i|
|
57
57
|
item = "NULL" if item.nil?
|
58
58
|
justifier = item.is_a?(Numeric) ? "rjust" : "ljust"
|
59
|
-
cells << item.to_s.
|
59
|
+
cells << item.to_s.public_send(justifier, widths[i])
|
60
60
|
end
|
61
61
|
"| " + cells.join(" | ") + " |"
|
62
62
|
end
|
@@ -3,7 +3,7 @@
|
|
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
|
@@ -11,6 +11,10 @@ module ActiveRecord
|
|
11
11
|
"DROP FOREIGN KEY #{name}"
|
12
12
|
end
|
13
13
|
|
14
|
+
def visit_DropCheckConstraint(name)
|
15
|
+
"DROP #{mariadb? ? 'CONSTRAINT' : 'CHECK'} #{name}"
|
16
|
+
end
|
17
|
+
|
14
18
|
def visit_AddColumnDefinition(o)
|
15
19
|
add_column_position!(super, column_options(o.column))
|
16
20
|
end
|
@@ -20,15 +24,37 @@ module ActiveRecord
|
|
20
24
|
add_column_position!(change_column_sql, column_options(o.column))
|
21
25
|
end
|
22
26
|
|
23
|
-
def
|
24
|
-
|
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)
|
25
51
|
end
|
26
52
|
|
27
53
|
def add_column_options!(sql, options)
|
28
54
|
# By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values,
|
29
55
|
# and assigning NULL assigns the current timestamp. To permit a TIMESTAMP
|
30
56
|
# column to contain NULL, explicitly declare it with the NULL attribute.
|
31
|
-
# See https://dev.mysql.com/doc/refman/
|
57
|
+
# See https://dev.mysql.com/doc/refman/en/timestamp-initialization.html
|
32
58
|
if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key]
|
33
59
|
sql << " NULL" unless options[:null] == false || options_include_default?(options)
|
34
60
|
end
|
@@ -62,8 +88,8 @@ module ActiveRecord
|
|
62
88
|
end
|
63
89
|
|
64
90
|
def index_in_create(table_name, column_name, options)
|
65
|
-
|
66
|
-
|
91
|
+
index, _ = @conn.add_index_options(table_name, column_name, **options)
|
92
|
+
accept(index)
|
67
93
|
end
|
68
94
|
end
|
69
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)
|
@@ -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)
|
@@ -203,10 +203,14 @@ module ActiveRecord
|
|
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
|
#--
|
@@ -124,7 +135,7 @@ module ActiveRecord
|
|
124
135
|
|
125
136
|
private
|
126
137
|
def connect
|
127
|
-
@connection =
|
138
|
+
@connection = self.class.new_client(@config)
|
128
139
|
configure_connection
|
129
140
|
end
|
130
141
|
|
@@ -140,6 +151,14 @@ module ActiveRecord
|
|
140
151
|
def get_full_version
|
141
152
|
@connection.server_info[:version]
|
142
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
|
143
162
|
end
|
144
163
|
end
|
145
164
|
end
|