activerecord 5.2.8.1 → 6.1.6.1
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 +1255 -596
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +9 -8
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +100 -41
- data/lib/active_record/associations/association_scope.rb +23 -21
- data/lib/active_record/associations/belongs_to_association.rb +55 -48
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
- data/lib/active_record/associations/builder/association.rb +45 -22
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +44 -34
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +69 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +137 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +46 -9
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
- data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- 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 +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- 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 +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
- data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +293 -33
- data/lib/active_record/core.rb +333 -98
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +273 -0
- 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 +3 -4
- data/lib/active_record/enum.rb +108 -36
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- 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 +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +200 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +28 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +37 -23
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +35 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +145 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +206 -157
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +116 -59
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +411 -80
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +62 -45
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +476 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +115 -62
- data/lib/active_record/relation.rb +379 -115
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +4 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- 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 +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +277 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +62 -118
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- 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 +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- 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 +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- 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
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +116 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -5,7 +5,9 @@ module ActiveRecord
|
|
5
5
|
module ConnectionAdapters
|
6
6
|
# An abstract definition of a column in a table.
|
7
7
|
class Column
|
8
|
-
|
8
|
+
include Deduplicable
|
9
|
+
|
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
|
11
13
|
|
@@ -15,9 +17,8 @@ module ActiveRecord
|
|
15
17
|
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
16
18
|
# +sql_type_metadata+ is various information about the type of the column
|
17
19
|
# +null+ determines if this column allows +NULL+ values.
|
18
|
-
def initialize(name, default, sql_type_metadata = nil, null = true,
|
20
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, default_function = nil, collation: nil, comment: nil, **)
|
19
21
|
@name = name.freeze
|
20
|
-
@table_name = table_name
|
21
22
|
@sql_type_metadata = sql_type_metadata
|
22
23
|
@null = null
|
23
24
|
@default = default
|
@@ -44,7 +45,6 @@ module ActiveRecord
|
|
44
45
|
|
45
46
|
def init_with(coder)
|
46
47
|
@name = coder["name"]
|
47
|
-
@table_name = coder["table_name"]
|
48
48
|
@sql_type_metadata = coder["sql_type_metadata"]
|
49
49
|
@null = coder["null"]
|
50
50
|
@default = coder["default"]
|
@@ -55,7 +55,6 @@ module ActiveRecord
|
|
55
55
|
|
56
56
|
def encode_with(coder)
|
57
57
|
coder["name"] = @name
|
58
|
-
coder["table_name"] = @table_name
|
59
58
|
coder["sql_type_metadata"] = @sql_type_metadata
|
60
59
|
coder["null"] = @null
|
61
60
|
coder["default"] = @default
|
@@ -66,23 +65,42 @@ module ActiveRecord
|
|
66
65
|
|
67
66
|
def ==(other)
|
68
67
|
other.is_a?(Column) &&
|
69
|
-
|
68
|
+
name == other.name &&
|
69
|
+
default == other.default &&
|
70
|
+
sql_type_metadata == other.sql_type_metadata &&
|
71
|
+
null == other.null &&
|
72
|
+
default_function == other.default_function &&
|
73
|
+
collation == other.collation &&
|
74
|
+
comment == other.comment
|
70
75
|
end
|
71
76
|
alias :eql? :==
|
72
77
|
|
73
78
|
def hash
|
74
|
-
|
79
|
+
Column.hash ^
|
80
|
+
name.hash ^
|
81
|
+
name.encoding.hash ^
|
82
|
+
default.hash ^
|
83
|
+
sql_type_metadata.hash ^
|
84
|
+
null.hash ^
|
85
|
+
default_function.hash ^
|
86
|
+
collation.hash ^
|
87
|
+
comment.hash
|
75
88
|
end
|
76
89
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
81
99
|
end
|
82
100
|
end
|
83
101
|
|
84
102
|
class NullColumn < Column
|
85
|
-
def initialize(name)
|
103
|
+
def initialize(name, **)
|
86
104
|
super(name, nil)
|
87
105
|
end
|
88
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,35 @@
|
|
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(role, shard, pool_config)
|
27
|
+
if pool_config
|
28
|
+
@name_to_pool_config[shard] = pool_config
|
29
|
+
else
|
30
|
+
raise ArgumentError, "The `pool_config` for the :#{role} role and :#{shard} shard was `nil`. Please check your configuration. If you want your writing role to be something other than `:writing` set `config.active_record.writing_role` in your application configuration. The same setting should be applied for the `reading_role` if applicable."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -5,13 +5,13 @@ 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
|
12
12
|
super
|
13
13
|
end
|
14
|
-
|
14
|
+
@connection.abandon_results!
|
15
15
|
result
|
16
16
|
end
|
17
17
|
|
@@ -19,8 +19,32 @@ module ActiveRecord
|
|
19
19
|
execute(sql, name).to_a
|
20
20
|
end
|
21
21
|
|
22
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
23
|
+
:desc, :describe, :set, :show, :use
|
24
|
+
) # :nodoc:
|
25
|
+
private_constant :READ_QUERY
|
26
|
+
|
27
|
+
def write_query?(sql) # :nodoc:
|
28
|
+
!READ_QUERY.match?(sql)
|
29
|
+
rescue ArgumentError # Invalid encoding
|
30
|
+
!READ_QUERY.match?(sql.b)
|
31
|
+
end
|
32
|
+
|
33
|
+
def explain(arel, binds = [])
|
34
|
+
sql = "EXPLAIN #{to_sql(arel, binds)}"
|
35
|
+
start = Concurrent.monotonic_time
|
36
|
+
result = exec_query(sql, "EXPLAIN", binds)
|
37
|
+
elapsed = Concurrent.monotonic_time - start
|
38
|
+
|
39
|
+
MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
|
40
|
+
end
|
41
|
+
|
22
42
|
# Executes the SQL statement in the context of this connection.
|
23
43
|
def execute(sql, name = nil)
|
44
|
+
if preventing_writes? && write_query?(sql)
|
45
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
46
|
+
end
|
47
|
+
|
24
48
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
25
49
|
# made since we established the connection
|
26
50
|
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
@@ -31,18 +55,28 @@ module ActiveRecord
|
|
31
55
|
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
32
56
|
if without_prepared_statement?(binds)
|
33
57
|
execute_and_free(sql, name) do |result|
|
34
|
-
|
58
|
+
if result
|
59
|
+
build_result(columns: result.fields, rows: result.to_a)
|
60
|
+
else
|
61
|
+
build_result(columns: [], rows: [])
|
62
|
+
end
|
35
63
|
end
|
36
64
|
else
|
37
65
|
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
|
38
|
-
|
66
|
+
if result
|
67
|
+
build_result(columns: result.fields, rows: result.to_a)
|
68
|
+
else
|
69
|
+
build_result(columns: [], rows: [])
|
70
|
+
end
|
39
71
|
end
|
40
72
|
end
|
41
73
|
end
|
42
74
|
|
43
75
|
def exec_delete(sql, name = nil, binds = [])
|
44
76
|
if without_prepared_statement?(binds)
|
45
|
-
|
77
|
+
@lock.synchronize do
|
78
|
+
execute_and_free(sql, name) { @connection.affected_rows }
|
79
|
+
end
|
46
80
|
else
|
47
81
|
exec_stmt_and_free(sql, name, binds) { |stmt| stmt.affected_rows }
|
48
82
|
end
|
@@ -50,55 +84,80 @@ module ActiveRecord
|
|
50
84
|
alias :exec_update :exec_delete
|
51
85
|
|
52
86
|
private
|
87
|
+
def execute_batch(statements, name = nil)
|
88
|
+
combine_multi_statements(statements).each do |statement|
|
89
|
+
execute(statement, name)
|
90
|
+
end
|
91
|
+
@connection.abandon_results!
|
92
|
+
end
|
93
|
+
|
53
94
|
def default_insert_value(column)
|
54
|
-
|
95
|
+
super unless column.auto_increment?
|
55
96
|
end
|
56
97
|
|
57
98
|
def last_inserted_id(result)
|
58
99
|
@connection.last_id
|
59
100
|
end
|
60
101
|
|
61
|
-
def
|
62
|
-
|
63
|
-
end
|
102
|
+
def multi_statements_enabled?
|
103
|
+
flags = @config[:flags]
|
64
104
|
|
65
|
-
def supports_set_server_option?
|
66
|
-
@connection.respond_to?(:set_server_option)
|
67
|
-
end
|
68
|
-
|
69
|
-
def multi_statements_enabled?(flags)
|
70
105
|
if flags.is_a?(Array)
|
71
106
|
flags.include?("MULTI_STATEMENTS")
|
72
107
|
else
|
73
|
-
(
|
108
|
+
flags.anybits?(Mysql2::Client::MULTI_STATEMENTS)
|
74
109
|
end
|
75
110
|
end
|
76
111
|
|
77
112
|
def with_multi_statements
|
78
|
-
|
113
|
+
multi_statements_was = multi_statements_enabled?
|
79
114
|
|
80
|
-
unless
|
81
|
-
|
82
|
-
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
83
|
-
else
|
84
|
-
@config[:flags] = Mysql2::Client::MULTI_STATEMENTS
|
85
|
-
reconnect!
|
86
|
-
end
|
115
|
+
unless multi_statements_was
|
116
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
87
117
|
end
|
88
118
|
|
89
119
|
yield
|
90
120
|
ensure
|
91
|
-
unless
|
92
|
-
|
93
|
-
|
121
|
+
unless multi_statements_was
|
122
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def combine_multi_statements(total_sql)
|
127
|
+
total_sql.each_with_object([]) do |sql, total_sql_chunks|
|
128
|
+
previous_packet = total_sql_chunks.last
|
129
|
+
if max_allowed_packet_reached?(sql, previous_packet)
|
130
|
+
total_sql_chunks << +sql
|
94
131
|
else
|
95
|
-
|
96
|
-
|
132
|
+
previous_packet << ";\n"
|
133
|
+
previous_packet << sql
|
97
134
|
end
|
98
135
|
end
|
99
136
|
end
|
100
137
|
|
138
|
+
def max_allowed_packet_reached?(current_packet, previous_packet)
|
139
|
+
if current_packet.bytesize > max_allowed_packet
|
140
|
+
raise ActiveRecordError,
|
141
|
+
"Fixtures set is too large #{current_packet.bytesize}. Consider increasing the max_allowed_packet variable."
|
142
|
+
elsif previous_packet.nil?
|
143
|
+
true
|
144
|
+
else
|
145
|
+
(current_packet.bytesize + previous_packet.bytesize + 2) > max_allowed_packet
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def max_allowed_packet
|
150
|
+
@max_allowed_packet ||= show_variable("max_allowed_packet")
|
151
|
+
end
|
152
|
+
|
101
153
|
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
154
|
+
if preventing_writes? && write_query?(sql)
|
155
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
156
|
+
end
|
157
|
+
|
158
|
+
materialize_transactions
|
159
|
+
mark_transaction_written_if_write(sql)
|
160
|
+
|
102
161
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
103
162
|
# made since we established the connection
|
104
163
|
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
@@ -107,10 +166,7 @@ module ActiveRecord
|
|
107
166
|
|
108
167
|
log(sql, name, binds, type_casted_binds) do
|
109
168
|
if cache_stmt
|
110
|
-
|
111
|
-
stmt: @connection.prepare(sql)
|
112
|
-
}
|
113
|
-
stmt = cache[:stmt]
|
169
|
+
stmt = @statements[sql] ||= @connection.prepare(sql)
|
114
170
|
else
|
115
171
|
stmt = @connection.prepare(sql)
|
116
172
|
end
|
@@ -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
|
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/time_with_zone"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters
|
5
7
|
module MySQL
|
6
8
|
module Quoting # :nodoc:
|
7
9
|
def quote_column_name(name)
|
8
|
-
|
10
|
+
self.class.quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
|
9
11
|
end
|
10
12
|
|
11
13
|
def quote_table_name(name)
|
12
|
-
|
14
|
+
self.class.quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
|
13
15
|
end
|
14
16
|
|
15
17
|
def unquoted_true
|
@@ -32,12 +34,62 @@ module ActiveRecord
|
|
32
34
|
"x'#{value.hex}'"
|
33
35
|
end
|
34
36
|
|
35
|
-
def
|
36
|
-
|
37
|
-
when Date, Time then value
|
38
|
-
else super
|
39
|
-
end
|
37
|
+
def column_name_matcher
|
38
|
+
COLUMN_NAME
|
40
39
|
end
|
40
|
+
|
41
|
+
def column_name_with_order_matcher
|
42
|
+
COLUMN_NAME_WITH_ORDER
|
43
|
+
end
|
44
|
+
|
45
|
+
COLUMN_NAME = /
|
46
|
+
\A
|
47
|
+
(
|
48
|
+
(?:
|
49
|
+
# `table_name`.`column_name` | function(one or no argument)
|
50
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
51
|
+
)
|
52
|
+
(?:(?:\s+AS)?\s+(?:\w+|`\w+`))?
|
53
|
+
)
|
54
|
+
(?:\s*,\s*\g<1>)*
|
55
|
+
\z
|
56
|
+
/ix
|
57
|
+
|
58
|
+
COLUMN_NAME_WITH_ORDER = /
|
59
|
+
\A
|
60
|
+
(
|
61
|
+
(?:
|
62
|
+
# `table_name`.`column_name` | function(one or no argument)
|
63
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
64
|
+
)
|
65
|
+
(?:\s+ASC|\s+DESC)?
|
66
|
+
)
|
67
|
+
(?:\s*,\s*\g<1>)*
|
68
|
+
\z
|
69
|
+
/ix
|
70
|
+
|
71
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
72
|
+
|
73
|
+
private
|
74
|
+
# Override +_type_cast+ we pass to mysql2 Date and Time objects instead
|
75
|
+
# of Strings since mysql2 is able to handle those classes more efficiently.
|
76
|
+
def _type_cast(value)
|
77
|
+
case value
|
78
|
+
when ActiveSupport::TimeWithZone
|
79
|
+
# We need to check explicitly for ActiveSupport::TimeWithZone because
|
80
|
+
# we need to transform it to Time objects but we don't want to
|
81
|
+
# transform Time objects to themselves.
|
82
|
+
if ActiveRecord::Base.default_timezone == :utc
|
83
|
+
value.getutc
|
84
|
+
else
|
85
|
+
value.getlocal
|
86
|
+
end
|
87
|
+
when Date, Time
|
88
|
+
value
|
89
|
+
else
|
90
|
+
super
|
91
|
+
end
|
92
|
+
end
|
41
93
|
end
|
42
94
|
end
|
43
95
|
end
|
@@ -3,34 +3,58 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module MySQL
|
6
|
-
class SchemaCreation <
|
7
|
-
delegate :add_sql_comment!, :mariadb?, to: :@conn
|
8
|
-
private :add_sql_comment!, :mariadb?
|
6
|
+
class SchemaCreation < SchemaCreation # :nodoc:
|
7
|
+
delegate :add_sql_comment!, :mariadb?, to: :@conn, private: true
|
9
8
|
|
10
9
|
private
|
11
|
-
|
12
10
|
def visit_DropForeignKey(name)
|
13
11
|
"DROP FOREIGN KEY #{name}"
|
14
12
|
end
|
15
13
|
|
14
|
+
def visit_DropCheckConstraint(name)
|
15
|
+
"DROP #{mariadb? ? 'CONSTRAINT' : 'CHECK'} #{name}"
|
16
|
+
end
|
17
|
+
|
16
18
|
def visit_AddColumnDefinition(o)
|
17
19
|
add_column_position!(super, column_options(o.column))
|
18
20
|
end
|
19
21
|
|
20
22
|
def visit_ChangeColumnDefinition(o)
|
21
|
-
change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
23
|
+
change_column_sql = +"CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
22
24
|
add_column_position!(change_column_sql, column_options(o.column))
|
23
25
|
end
|
24
26
|
|
25
|
-
def
|
26
|
-
|
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)
|
27
51
|
end
|
28
52
|
|
29
53
|
def add_column_options!(sql, options)
|
30
54
|
# By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values,
|
31
55
|
# and assigning NULL assigns the current timestamp. To permit a TIMESTAMP
|
32
56
|
# column to contain NULL, explicitly declare it with the NULL attribute.
|
33
|
-
# See https://dev.mysql.com/doc/refman/
|
57
|
+
# See https://dev.mysql.com/doc/refman/en/timestamp-initialization.html
|
34
58
|
if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key]
|
35
59
|
sql << " NULL" unless options[:null] == false || options_include_default?(options)
|
36
60
|
end
|
@@ -64,8 +88,8 @@ module ActiveRecord
|
|
64
88
|
end
|
65
89
|
|
66
90
|
def index_in_create(table_name, column_name, options)
|
67
|
-
|
68
|
-
|
91
|
+
index, _ = @conn.add_index_options(table_name, column_name, **options)
|
92
|
+
accept(index)
|
69
93
|
end
|
70
94
|
end
|
71
95
|
end
|
@@ -4,54 +4,70 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module MySQL
|
6
6
|
module ColumnMethods
|
7
|
-
|
8
|
-
args.each { |name| column(name, :blob, options) }
|
9
|
-
end
|
7
|
+
extend ActiveSupport::Concern
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
##
|
10
|
+
# :method: blob
|
11
|
+
# :call-seq: blob(*names, **options)
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
##
|
14
|
+
# :method: tinyblob
|
15
|
+
# :call-seq: tinyblob(*names, **options)
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
##
|
18
|
+
# :method: mediumblob
|
19
|
+
# :call-seq: mediumblob(*names, **options)
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
##
|
22
|
+
# :method: longblob
|
23
|
+
# :call-seq: longblob(*names, **options)
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
##
|
26
|
+
# :method: tinytext
|
27
|
+
# :call-seq: tinytext(*names, **options)
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
##
|
30
|
+
# :method: mediumtext
|
31
|
+
# :call-seq: mediumtext(*names, **options)
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
##
|
34
|
+
# :method: longtext
|
35
|
+
# :call-seq: longtext(*names, **options)
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
##
|
38
|
+
# :method: unsigned_integer
|
39
|
+
# :call-seq: unsigned_integer(*names, **options)
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
##
|
42
|
+
# :method: unsigned_bigint
|
43
|
+
# :call-seq: unsigned_bigint(*names, **options)
|
44
|
+
|
45
|
+
##
|
46
|
+
# :method: unsigned_float
|
47
|
+
# :call-seq: unsigned_float(*names, **options)
|
48
|
+
|
49
|
+
##
|
50
|
+
# :method: unsigned_decimal
|
51
|
+
# :call-seq: unsigned_decimal(*names, **options)
|
46
52
|
|
47
|
-
|
48
|
-
|
53
|
+
included do
|
54
|
+
define_column_methods :blob, :tinyblob, :mediumblob, :longblob,
|
55
|
+
:tinytext, :mediumtext, :longtext, :unsigned_integer, :unsigned_bigint,
|
56
|
+
:unsigned_float, :unsigned_decimal
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
52
60
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
53
61
|
include ColumnMethods
|
54
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
|
+
|
55
71
|
def new_column_definition(name, type, **options) # :nodoc:
|
56
72
|
case type
|
57
73
|
when :virtual
|