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
data/lib/active_record/errors.rb
CHANGED
@@ -7,6 +7,10 @@ module ActiveRecord
|
|
7
7
|
class ActiveRecordError < StandardError
|
8
8
|
end
|
9
9
|
|
10
|
+
# Raised when trying to use a feature in Active Record which requires Active Job but the gem is not present.
|
11
|
+
class ActiveJobRequiredError < ActiveRecordError
|
12
|
+
end
|
13
|
+
|
10
14
|
# Raised when the single-table inheritance mechanism fails to locate the subclass
|
11
15
|
# (for example due to improper usage of column that
|
12
16
|
# {ActiveRecord::Base.inheritance_column}[rdoc-ref:ModelSchema::ClassMethods#inheritance_column]
|
@@ -38,6 +42,10 @@ module ActiveRecord
|
|
38
42
|
class AdapterNotSpecified < ActiveRecordError
|
39
43
|
end
|
40
44
|
|
45
|
+
# Raised when a model makes a query but it has not specified an associated table.
|
46
|
+
class TableNotSpecified < ActiveRecordError
|
47
|
+
end
|
48
|
+
|
41
49
|
# Raised when Active Record cannot find database adapter specified in
|
42
50
|
# +config/database.yml+ or programmatically.
|
43
51
|
class AdapterNotFound < ActiveRecordError
|
@@ -49,6 +57,23 @@ module ActiveRecord
|
|
49
57
|
class ConnectionNotEstablished < ActiveRecordError
|
50
58
|
end
|
51
59
|
|
60
|
+
# Raised when a connection could not be obtained within the connection
|
61
|
+
# acquisition timeout period: because max connections in pool
|
62
|
+
# are in use.
|
63
|
+
class ConnectionTimeoutError < ConnectionNotEstablished
|
64
|
+
end
|
65
|
+
|
66
|
+
# Raised when a pool was unable to get ahold of all its connections
|
67
|
+
# to perform a "group" action such as
|
68
|
+
# {ActiveRecord::Base.connection_pool.disconnect!}[rdoc-ref:ConnectionAdapters::ConnectionPool#disconnect!]
|
69
|
+
# or {ActiveRecord::Base.clear_reloadable_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_reloadable_connections!].
|
70
|
+
class ExclusiveConnectionTimeoutError < ConnectionTimeoutError
|
71
|
+
end
|
72
|
+
|
73
|
+
# Raised when a write to the database is attempted on a read only connection.
|
74
|
+
class ReadOnlyError < ActiveRecordError
|
75
|
+
end
|
76
|
+
|
52
77
|
# Raised when Active Record cannot find a record by given id or set of ids.
|
53
78
|
class RecordNotFound < ActiveRecordError
|
54
79
|
attr_reader :model, :primary_key, :id
|
@@ -64,7 +89,7 @@ module ActiveRecord
|
|
64
89
|
|
65
90
|
# Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
|
66
91
|
# {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
|
67
|
-
# methods when a record is invalid and
|
92
|
+
# methods when a record is invalid and cannot be saved.
|
68
93
|
class RecordNotSaved < ActiveRecordError
|
69
94
|
attr_reader :record
|
70
95
|
|
@@ -97,9 +122,13 @@ module ActiveRecord
|
|
97
122
|
#
|
98
123
|
# Wraps the underlying database error as +cause+.
|
99
124
|
class StatementInvalid < ActiveRecordError
|
100
|
-
def initialize(message = nil)
|
101
|
-
super(message ||
|
125
|
+
def initialize(message = nil, sql: nil, binds: nil)
|
126
|
+
super(message || $!&.message)
|
127
|
+
@sql = sql
|
128
|
+
@binds = binds
|
102
129
|
end
|
130
|
+
|
131
|
+
attr_reader :sql, :binds
|
103
132
|
end
|
104
133
|
|
105
134
|
# Defunct wrapper class kept for compatibility.
|
@@ -111,14 +140,14 @@ module ActiveRecord
|
|
111
140
|
class RecordNotUnique < WrappedDatabaseException
|
112
141
|
end
|
113
142
|
|
114
|
-
# Raised when a record cannot be inserted or updated because it references a non-existent record
|
143
|
+
# Raised when a record cannot be inserted or updated because it references a non-existent record,
|
144
|
+
# or when a record cannot be deleted because a parent record references it.
|
115
145
|
class InvalidForeignKey < WrappedDatabaseException
|
116
146
|
end
|
117
147
|
|
118
148
|
# Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type.
|
119
149
|
class MismatchedForeignKey < StatementInvalid
|
120
150
|
def initialize(
|
121
|
-
adapter = nil,
|
122
151
|
message: nil,
|
123
152
|
sql: nil,
|
124
153
|
binds: nil,
|
@@ -130,14 +159,14 @@ module ActiveRecord
|
|
130
159
|
)
|
131
160
|
if table
|
132
161
|
type = primary_key_column.bigint? ? :bigint : primary_key_column.type
|
133
|
-
msg =
|
162
|
+
msg = <<~EOM.squish
|
134
163
|
Column `#{foreign_key}` on table `#{table}` does not match column `#{primary_key}` on `#{target_table}`,
|
135
164
|
which has type `#{primary_key_column.sql_type}`.
|
136
165
|
To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :#{type}.
|
137
166
|
(For example `t.#{type} :#{foreign_key}`).
|
138
167
|
EOM
|
139
168
|
else
|
140
|
-
msg =
|
169
|
+
msg = <<~EOM.squish
|
141
170
|
There is a mismatch between the foreign key and primary key column types.
|
142
171
|
Verify that the foreign key column type and the primary key of the associated table match types.
|
143
172
|
EOM
|
@@ -145,7 +174,7 @@ module ActiveRecord
|
|
145
174
|
if message
|
146
175
|
msg << "\nOriginal message: #{message}"
|
147
176
|
end
|
148
|
-
super(msg)
|
177
|
+
super(msg, sql: sql, binds: binds)
|
149
178
|
end
|
150
179
|
end
|
151
180
|
|
@@ -161,9 +190,9 @@ module ActiveRecord
|
|
161
190
|
class RangeError < StatementInvalid
|
162
191
|
end
|
163
192
|
|
164
|
-
# Raised when number of
|
165
|
-
#
|
166
|
-
# does not match number of
|
193
|
+
# Raised when the number of placeholders in an SQL fragment passed to
|
194
|
+
# {ActiveRecord::Base.where}[rdoc-ref:QueryMethods#where]
|
195
|
+
# does not match the number of values supplied.
|
167
196
|
#
|
168
197
|
# For example, when there are two placeholders with only one value supplied:
|
169
198
|
#
|
@@ -175,6 +204,10 @@ module ActiveRecord
|
|
175
204
|
class NoDatabaseError < StatementInvalid
|
176
205
|
end
|
177
206
|
|
207
|
+
# Raised when creating a database if it exists.
|
208
|
+
class DatabaseAlreadyExists < StatementInvalid
|
209
|
+
end
|
210
|
+
|
178
211
|
# Raised when PostgreSQL returns 'cached plan must not change result type' and
|
179
212
|
# we cannot retry gracefully (e.g. inside a transaction)
|
180
213
|
class PreparedStatementCacheExpired < StatementInvalid
|
@@ -212,6 +245,10 @@ module ActiveRecord
|
|
212
245
|
class ReadOnlyRecord < ActiveRecordError
|
213
246
|
end
|
214
247
|
|
248
|
+
# Raised on attempt to lazily load records that are marked as strict loading.
|
249
|
+
class StrictLoadingViolationError < ActiveRecordError
|
250
|
+
end
|
251
|
+
|
215
252
|
# {ActiveRecord::Base.transaction}[rdoc-ref:Transactions::ClassMethods#transaction]
|
216
253
|
# uses this exception to distinguish a deliberate rollback from other exceptional situations.
|
217
254
|
# Normally, raising an exception will cause the
|
@@ -322,7 +359,7 @@ module ActiveRecord
|
|
322
359
|
# See the following:
|
323
360
|
#
|
324
361
|
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
325
|
-
# * https://dev.mysql.com/doc/
|
362
|
+
# * https://dev.mysql.com/doc/mysql-errors/en/server-error-reference.html#error_er_lock_deadlock
|
326
363
|
class TransactionRollbackError < StatementInvalid
|
327
364
|
end
|
328
365
|
|
@@ -341,30 +378,36 @@ module ActiveRecord
|
|
341
378
|
class IrreversibleOrderError < ActiveRecordError
|
342
379
|
end
|
343
380
|
|
381
|
+
# Superclass for errors that have been aborted (either by client or server).
|
382
|
+
class QueryAborted < StatementInvalid
|
383
|
+
end
|
384
|
+
|
344
385
|
# LockWaitTimeout will be raised when lock wait timeout exceeded.
|
345
386
|
class LockWaitTimeout < StatementInvalid
|
346
387
|
end
|
347
388
|
|
348
389
|
# StatementTimeout will be raised when statement timeout exceeded.
|
349
|
-
class StatementTimeout <
|
390
|
+
class StatementTimeout < QueryAborted
|
350
391
|
end
|
351
392
|
|
352
393
|
# QueryCanceled will be raised when canceling statement due to user request.
|
353
|
-
class QueryCanceled <
|
394
|
+
class QueryCanceled < QueryAborted
|
395
|
+
end
|
396
|
+
|
397
|
+
# AdapterTimeout will be raised when database clients times out while waiting from the server.
|
398
|
+
class AdapterTimeout < QueryAborted
|
354
399
|
end
|
355
400
|
|
356
401
|
# UnknownAttributeReference is raised when an unknown and potentially unsafe
|
357
|
-
# value is passed to a query method
|
358
|
-
#
|
359
|
-
# #order method might cause this exception.
|
402
|
+
# value is passed to a query method. For example, passing a non column name
|
403
|
+
# value to a relation's #order method might cause this exception.
|
360
404
|
#
|
361
405
|
# When working around this exception, caution should be taken to avoid SQL
|
362
406
|
# injection vulnerabilities when passing user-provided values to query
|
363
407
|
# methods. Known-safe values can be passed to query methods by wrapping them
|
364
408
|
# in Arel.sql.
|
365
409
|
#
|
366
|
-
# For example,
|
367
|
-
# code would raise this exception:
|
410
|
+
# For example, the following code would raise this exception:
|
368
411
|
#
|
369
412
|
# Post.order("length(title)").first
|
370
413
|
#
|
@@ -18,7 +18,7 @@ module ActiveRecord
|
|
18
18
|
# Returns a formatted string ready to be logged.
|
19
19
|
def exec_explain(queries) # :nodoc:
|
20
20
|
str = queries.map do |sql, binds|
|
21
|
-
msg = "EXPLAIN for: #{sql}"
|
21
|
+
msg = +"EXPLAIN for: #{sql}"
|
22
22
|
unless binds.empty?
|
23
23
|
msg << " "
|
24
24
|
msg << binds.map { |attr| render_bind(attr) }.inspect
|
@@ -36,15 +36,19 @@ module ActiveRecord
|
|
36
36
|
end
|
37
37
|
|
38
38
|
private
|
39
|
-
|
40
39
|
def render_bind(attr)
|
41
|
-
|
42
|
-
|
40
|
+
if ActiveModel::Attribute === attr
|
41
|
+
value = if attr.type.binary? && attr.value
|
42
|
+
"<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
|
43
|
+
else
|
44
|
+
connection.type_cast(attr.value_for_database)
|
45
|
+
end
|
43
46
|
else
|
44
|
-
connection.type_cast(attr
|
47
|
+
value = connection.type_cast(attr)
|
48
|
+
attr = nil
|
45
49
|
end
|
46
50
|
|
47
|
-
[attr
|
51
|
+
[attr&.name, value]
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -26,7 +26,7 @@ module ActiveRecord
|
|
26
26
|
payload[:exception] ||
|
27
27
|
payload[:cached] ||
|
28
28
|
IGNORED_PAYLOADS.include?(payload[:name]) ||
|
29
|
-
payload[:sql]
|
29
|
+
!payload[:sql].match?(EXPLAINED_SQLS)
|
30
30
|
end
|
31
31
|
|
32
32
|
ActiveSupport::Notifications.subscribe("sql.active_record", new)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
4
|
-
require "yaml"
|
3
|
+
require "active_support/configuration_file"
|
5
4
|
|
6
5
|
module ActiveRecord
|
7
6
|
class FixtureSet
|
@@ -29,6 +28,10 @@ module ActiveRecord
|
|
29
28
|
config_row["model_class"]
|
30
29
|
end
|
31
30
|
|
31
|
+
def ignored_fixtures
|
32
|
+
config_row["ignore"]
|
33
|
+
end
|
34
|
+
|
32
35
|
private
|
33
36
|
def rows
|
34
37
|
@rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
|
@@ -40,31 +43,21 @@ module ActiveRecord
|
|
40
43
|
if row
|
41
44
|
row.last
|
42
45
|
else
|
43
|
-
{ 'model_class': nil }
|
46
|
+
{ 'model_class': nil, 'ignore': nil }
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
51
|
def raw_rows
|
49
52
|
@raw_rows ||= begin
|
50
|
-
data =
|
53
|
+
data = ActiveSupport::ConfigurationFile.parse(@file, context:
|
54
|
+
ActiveRecord::FixtureSet::RenderContext.create_subclass.new.get_binding)
|
51
55
|
data ? validate(data).to_a : []
|
52
|
-
rescue
|
53
|
-
raise Fixture::FormatError,
|
56
|
+
rescue RuntimeError => error
|
57
|
+
raise Fixture::FormatError, error.message
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
57
|
-
def prepare_erb(content)
|
58
|
-
erb = ERB.new(content)
|
59
|
-
erb.filename = @file
|
60
|
-
erb
|
61
|
-
end
|
62
|
-
|
63
|
-
def render(content)
|
64
|
-
context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new
|
65
|
-
prepare_erb(content).result(context.get_binding)
|
66
|
-
end
|
67
|
-
|
68
61
|
# Validate our unmarshalled data.
|
69
62
|
def validate(data)
|
70
63
|
unless Hash === data || YAML::Omap === data
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class FixtureSet
|
5
|
+
class ModelMetadata # :nodoc:
|
6
|
+
def initialize(model_class)
|
7
|
+
@model_class = model_class
|
8
|
+
end
|
9
|
+
|
10
|
+
def primary_key_name
|
11
|
+
@primary_key_name ||= @model_class && @model_class.primary_key
|
12
|
+
end
|
13
|
+
|
14
|
+
def primary_key_type
|
15
|
+
@primary_key_type ||= @model_class && @model_class.type_for_attribute(@model_class.primary_key).type
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_primary_key_column?
|
19
|
+
@has_primary_key_column ||= primary_key_name &&
|
20
|
+
@model_class.columns.any? { |col| col.name == primary_key_name }
|
21
|
+
end
|
22
|
+
|
23
|
+
def timestamp_column_names
|
24
|
+
@model_class.all_timestamp_attributes_in_model
|
25
|
+
end
|
26
|
+
|
27
|
+
def inheritance_column_name
|
28
|
+
@inheritance_column_name ||= @model_class && @model_class.inheritance_column
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE: This class has to be defined in compact style in
|
4
|
+
# order for rendering context subclassing to work correctly.
|
5
|
+
class ActiveRecord::FixtureSet::RenderContext # :nodoc:
|
6
|
+
def self.create_subclass
|
7
|
+
Class.new(ActiveRecord::FixtureSet.context_class) do
|
8
|
+
def get_binding
|
9
|
+
binding()
|
10
|
+
end
|
11
|
+
|
12
|
+
def binary(path)
|
13
|
+
%(!!binary "#{Base64.strict_encode64(File.binread(path))}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class FixtureSet
|
5
|
+
class TableRow # :nodoc:
|
6
|
+
class ReflectionProxy # :nodoc:
|
7
|
+
def initialize(association)
|
8
|
+
@association = association
|
9
|
+
end
|
10
|
+
|
11
|
+
def join_table
|
12
|
+
@association.join_table
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
@association.name
|
17
|
+
end
|
18
|
+
|
19
|
+
def primary_key_type
|
20
|
+
@association.klass.type_for_attribute(@association.klass.primary_key).type
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class HasManyThroughProxy < ReflectionProxy # :nodoc:
|
25
|
+
def rhs_key
|
26
|
+
@association.foreign_key
|
27
|
+
end
|
28
|
+
|
29
|
+
def lhs_key
|
30
|
+
@association.through_reflection.foreign_key
|
31
|
+
end
|
32
|
+
|
33
|
+
def join_table
|
34
|
+
@association.through_reflection.table_name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(fixture, table_rows:, label:, now:)
|
39
|
+
@table_rows = table_rows
|
40
|
+
@label = label
|
41
|
+
@now = now
|
42
|
+
@row = fixture.to_hash
|
43
|
+
fill_row_model_attributes
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_hash
|
47
|
+
@row
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def model_metadata
|
52
|
+
@table_rows.model_metadata
|
53
|
+
end
|
54
|
+
|
55
|
+
def model_class
|
56
|
+
@table_rows.model_class
|
57
|
+
end
|
58
|
+
|
59
|
+
def fill_row_model_attributes
|
60
|
+
return unless model_class
|
61
|
+
fill_timestamps
|
62
|
+
interpolate_label
|
63
|
+
generate_primary_key
|
64
|
+
resolve_enums
|
65
|
+
resolve_sti_reflections
|
66
|
+
end
|
67
|
+
|
68
|
+
def reflection_class
|
69
|
+
@reflection_class ||= if @row.include?(model_metadata.inheritance_column_name)
|
70
|
+
@row[model_metadata.inheritance_column_name].constantize rescue model_class
|
71
|
+
else
|
72
|
+
model_class
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def fill_timestamps
|
77
|
+
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
|
78
|
+
if model_class.record_timestamps
|
79
|
+
model_metadata.timestamp_column_names.each do |c_name|
|
80
|
+
@row[c_name] = @now unless @row.key?(c_name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def interpolate_label
|
86
|
+
# interpolate the fixture label
|
87
|
+
@row.each do |key, value|
|
88
|
+
@row[key] = value.gsub("$LABEL", @label.to_s) if value.is_a?(String)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def generate_primary_key
|
93
|
+
# generate a primary key if necessary
|
94
|
+
if model_metadata.has_primary_key_column? && !@row.include?(model_metadata.primary_key_name)
|
95
|
+
@row[model_metadata.primary_key_name] = ActiveRecord::FixtureSet.identify(
|
96
|
+
@label, model_metadata.primary_key_type
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def resolve_enums
|
102
|
+
model_class.defined_enums.each do |name, values|
|
103
|
+
if @row.include?(name)
|
104
|
+
@row[name] = values.fetch(@row[name], @row[name])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def resolve_sti_reflections
|
110
|
+
# If STI is used, find the correct subclass for association reflection
|
111
|
+
reflection_class._reflections.each_value do |association|
|
112
|
+
case association.macro
|
113
|
+
when :belongs_to
|
114
|
+
# Do not replace association name with association foreign key if they are named the same
|
115
|
+
fk_name = association.join_foreign_key
|
116
|
+
|
117
|
+
if association.name.to_s != fk_name && value = @row.delete(association.name.to_s)
|
118
|
+
if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
|
119
|
+
# support polymorphic belongs_to as "label (Type)"
|
120
|
+
@row[association.join_foreign_type] = $1
|
121
|
+
end
|
122
|
+
|
123
|
+
fk_type = reflection_class.type_for_attribute(fk_name).type
|
124
|
+
@row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
125
|
+
end
|
126
|
+
when :has_many
|
127
|
+
if association.options[:through]
|
128
|
+
add_join_records(HasManyThroughProxy.new(association))
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_join_records(association)
|
135
|
+
# This is the case when the join table has no fixtures file
|
136
|
+
if (targets = @row.delete(association.name.to_s))
|
137
|
+
table_name = association.join_table
|
138
|
+
column_type = association.primary_key_type
|
139
|
+
lhs_key = association.lhs_key
|
140
|
+
rhs_key = association.rhs_key
|
141
|
+
|
142
|
+
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
143
|
+
joins = targets.map do |target|
|
144
|
+
{ lhs_key => @row[model_metadata.primary_key_name],
|
145
|
+
rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
|
146
|
+
end
|
147
|
+
@table_rows.tables[table_name].concat(joins)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/fixture_set/table_row"
|
4
|
+
require "active_record/fixture_set/model_metadata"
|
5
|
+
|
6
|
+
module ActiveRecord
|
7
|
+
class FixtureSet
|
8
|
+
class TableRows # :nodoc:
|
9
|
+
def initialize(table_name, model_class:, fixtures:, config:)
|
10
|
+
@model_class = model_class
|
11
|
+
|
12
|
+
# track any join tables we need to insert later
|
13
|
+
@tables = Hash.new { |h, table| h[table] = [] }
|
14
|
+
|
15
|
+
# ensure this table is loaded before any HABTM associations
|
16
|
+
@tables[table_name] = nil
|
17
|
+
|
18
|
+
build_table_rows_from(table_name, fixtures, config)
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :tables, :model_class
|
22
|
+
|
23
|
+
def to_hash
|
24
|
+
@tables.transform_values { |rows| rows.map(&:to_hash) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def model_metadata
|
28
|
+
@model_metadata ||= ModelMetadata.new(model_class)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def build_table_rows_from(table_name, fixtures, config)
|
33
|
+
now = config.default_timezone == :utc ? Time.now.utc : Time.now
|
34
|
+
|
35
|
+
@tables[table_name] = fixtures.map do |label, fixture|
|
36
|
+
TableRow.new(
|
37
|
+
fixture,
|
38
|
+
table_rows: self,
|
39
|
+
label: label,
|
40
|
+
now: now,
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|