activerecord 5.0.7.2 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +829 -2015
- data/MIT-LICENSE +3 -1
- data/README.rdoc +11 -9
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record.rb +37 -29
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +30 -18
- data/lib/active_record/associations.rb +1714 -1596
- data/lib/active_record/associations/alias_tracker.rb +36 -42
- data/lib/active_record/associations/association.rb +143 -68
- data/lib/active_record/associations/association_scope.rb +98 -94
- data/lib/active_record/associations/belongs_to_association.rb +76 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +27 -28
- data/lib/active_record/associations/builder/belongs_to.rb +52 -60
- data/lib/active_record/associations/builder/collection_association.rb +12 -22
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
- data/lib/active_record/associations/builder/has_many.rb +10 -2
- data/lib/active_record/associations/builder/has_one.rb +35 -2
- data/lib/active_record/associations/builder/singular_association.rb +5 -1
- data/lib/active_record/associations/collection_association.rb +104 -259
- data/lib/active_record/associations/collection_proxy.rb +169 -125
- data/lib/active_record/associations/foreign_association.rb +22 -0
- data/lib/active_record/associations/has_many_association.rb +46 -31
- data/lib/active_record/associations/has_many_through_association.rb +66 -46
- data/lib/active_record/associations/has_one_association.rb +71 -52
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +169 -180
- data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/preloader.rb +97 -104
- data/lib/active_record/associations/preloader/association.rb +109 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/attribute_assignment.rb +55 -60
- data/lib/active_record/attribute_methods.rb +111 -141
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
- data/lib/active_record/attribute_methods/dirty.rb +172 -112
- data/lib/active_record/attribute_methods/primary_key.rb +88 -91
- data/lib/active_record/attribute_methods/query.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +18 -50
- data/lib/active_record/attribute_methods/serialization.rb +38 -10
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
- data/lib/active_record/attribute_methods/write.rb +25 -32
- data/lib/active_record/attributes.rb +69 -31
- data/lib/active_record/autosave_association.rb +102 -66
- data/lib/active_record/base.rb +16 -25
- data/lib/active_record/callbacks.rb +202 -43
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -12
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
- data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
- data/lib/active_record/connection_adapters/column.rb +55 -13
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
- 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 +39 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
- data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +287 -45
- data/lib/active_record/core.rb +385 -181
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -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/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +122 -47
- data/lib/active_record/errors.rb +153 -22
- data/lib/active_record/explain.rb +13 -8
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +20 -22
- 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 +246 -507
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +168 -95
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +114 -25
- data/lib/active_record/internal_metadata.rb +30 -24
- data/lib/active_record/legacy_yaml_adapter.rb +11 -5
- data/lib/active_record/locking/optimistic.rb +81 -85
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +68 -31
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/migration.rb +439 -342
- data/lib/active_record/migration/command_recorder.rb +152 -98
- data/lib/active_record/migration/compatibility.rb +229 -60
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/model_schema.rb +230 -122
- data/lib/active_record/nested_attributes.rb +213 -203
- data/lib/active_record/no_touching.rb +11 -2
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +471 -97
- data/lib/active_record/query_cache.rb +23 -12
- data/lib/active_record/querying.rb +43 -25
- data/lib/active_record/railtie.rb +155 -43
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +507 -195
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +245 -269
- data/lib/active_record/relation.rb +475 -324
- data/lib/active_record/relation/batches.rb +125 -72
- data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
- data/lib/active_record/relation/calculations.rb +267 -171
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +238 -248
- data/lib/active_record/relation/from_clause.rb +7 -9
- data/lib/active_record/relation/merger.rb +95 -77
- data/lib/active_record/relation/predicate_builder.rb +109 -110
- data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +654 -374
- data/lib/active_record/relation/record_fetch_warning.rb +8 -6
- data/lib/active_record/relation/spawn_methods.rb +15 -14
- data/lib/active_record/relation/where_clause.rb +171 -109
- data/lib/active_record/result.rb +88 -51
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +73 -100
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +101 -69
- data/lib/active_record/schema_migration.rb +16 -12
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +39 -30
- data/lib/active_record/secure_token.rb +19 -9
- data/lib/active_record/serialization.rb +7 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +80 -29
- data/lib/active_record/store.rb +122 -42
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +51 -39
- data/lib/active_record/tasks/database_tasks.rb +332 -115
- data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
- data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +26 -24
- data/lib/active_record/transactions.rb +121 -184
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +29 -17
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +20 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/type_caster/connection.rb +17 -13
- data/lib/active_record/type_caster/map.rb +10 -6
- data/lib/active_record/validations.rb +8 -5
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +4 -3
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +52 -45
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +54 -0
- 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.rb +70 -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 +72 -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/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.rb +13 -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/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +22 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
- 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 → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +141 -57
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute_decorators.rb +0 -67
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/relation/where_clause_factory.rb +0 -38
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,23 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class Relation
|
3
5
|
module RecordFetchWarning
|
4
6
|
# When this module is prepended to ActiveRecord::Relation and
|
5
|
-
#
|
7
|
+
# +config.active_record.warn_on_records_fetched_greater_than+ is
|
6
8
|
# set to an integer, if the number of records a query returns is
|
7
|
-
# greater than the value of
|
9
|
+
# greater than the value of +warn_on_records_fetched_greater_than+,
|
8
10
|
# a warning is logged. This allows for the detection of queries that
|
9
11
|
# return a large number of records, which could cause memory bloat.
|
10
12
|
#
|
11
13
|
# In most cases, fetching large number of records can be performed
|
12
14
|
# efficiently using the ActiveRecord::Batches methods.
|
13
|
-
# See
|
15
|
+
# See ActiveRecord::Batches for more information.
|
14
16
|
def exec_queries
|
15
17
|
QueryRegistry.reset
|
16
18
|
|
17
|
-
super.tap do
|
19
|
+
super.tap do |records|
|
18
20
|
if logger && warn_on_records_fetched_greater_than
|
19
|
-
if
|
20
|
-
logger.warn "Query fetched #{
|
21
|
+
if records.length > warn_on_records_fetched_greater_than
|
22
|
+
logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -1,13 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/except"
|
4
|
+
require "active_support/core_ext/hash/slice"
|
5
|
+
require "active_record/relation/merger"
|
4
6
|
|
5
7
|
module ActiveRecord
|
6
8
|
module SpawnMethods
|
7
|
-
|
8
9
|
# This is overridden by Associations::CollectionProxy
|
9
10
|
def spawn #:nodoc:
|
10
|
-
clone
|
11
|
+
already_in_scope? ? klass.all : clone
|
11
12
|
end
|
12
13
|
|
13
14
|
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
|
@@ -27,21 +28,22 @@ module ActiveRecord
|
|
27
28
|
# # => Post.where(published: true).joins(:comments)
|
28
29
|
#
|
29
30
|
# This is mainly intended for sharing common conditions between multiple associations.
|
30
|
-
def merge(other)
|
31
|
+
def merge(other, *rest)
|
31
32
|
if other.is_a?(Array)
|
32
33
|
records & other
|
33
34
|
elsif other
|
34
|
-
spawn.merge!(other)
|
35
|
+
spawn.merge!(other, *rest)
|
35
36
|
else
|
36
37
|
raise ArgumentError, "invalid argument: #{other.inspect}."
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
def merge!(other) # :nodoc:
|
41
|
+
def merge!(other, *rest) # :nodoc:
|
42
|
+
options = rest.extract_options!
|
41
43
|
if other.is_a?(Hash)
|
42
|
-
Relation::HashMerger.new(self, other).merge
|
44
|
+
Relation::HashMerger.new(self, other, options[:rewhere]).merge
|
43
45
|
elsif other.is_a?(Relation)
|
44
|
-
Relation::Merger.new(self, other).merge
|
46
|
+
Relation::Merger.new(self, other, options[:rewhere]).merge
|
45
47
|
elsif other.respond_to?(:to_proc)
|
46
48
|
instance_exec(&other)
|
47
49
|
else
|
@@ -66,10 +68,9 @@ module ActiveRecord
|
|
66
68
|
end
|
67
69
|
|
68
70
|
private
|
69
|
-
|
70
|
-
|
71
|
-
result
|
72
|
-
result.extend(*extending_values) if extending_values.any?
|
71
|
+
def relation_with(values)
|
72
|
+
result = spawn
|
73
|
+
result.instance_variable_set(:@values, values)
|
73
74
|
result
|
74
75
|
end
|
75
76
|
end
|
@@ -1,174 +1,236 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/array/extract"
|
4
|
+
|
1
5
|
module ActiveRecord
|
2
6
|
class Relation
|
3
7
|
class WhereClause # :nodoc:
|
4
|
-
attr_reader :binds
|
5
|
-
|
6
8
|
delegate :any?, :empty?, to: :predicates
|
7
9
|
|
8
|
-
def initialize(predicates
|
10
|
+
def initialize(predicates)
|
9
11
|
@predicates = predicates
|
10
|
-
@binds = binds
|
11
12
|
end
|
12
13
|
|
13
14
|
def +(other)
|
14
|
-
WhereClause.new(
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
WhereClause.new(predicates + other.predicates)
|
16
|
+
end
|
17
|
+
|
18
|
+
def -(other)
|
19
|
+
WhereClause.new(predicates - other.predicates)
|
18
20
|
end
|
19
21
|
|
20
|
-
def
|
21
|
-
WhereClause.new(
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
def |(other)
|
23
|
+
WhereClause.new(predicates | other.predicates)
|
24
|
+
end
|
25
|
+
|
26
|
+
def merge(other, rewhere = nil)
|
27
|
+
predicates = if rewhere
|
28
|
+
except_predicates(other.extract_attributes)
|
29
|
+
else
|
30
|
+
predicates_unreferenced_by(other)
|
31
|
+
end
|
32
|
+
|
33
|
+
WhereClause.new(predicates | other.predicates)
|
25
34
|
end
|
26
35
|
|
27
36
|
def except(*columns)
|
28
|
-
WhereClause.new(
|
29
|
-
predicates_except(columns),
|
30
|
-
binds_except(columns),
|
31
|
-
)
|
37
|
+
WhereClause.new(except_predicates(columns))
|
32
38
|
end
|
33
39
|
|
34
40
|
def or(other)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
41
|
+
left = self - other
|
42
|
+
common = self - left
|
43
|
+
right = other - common
|
44
|
+
|
45
|
+
if left.empty? || right.empty?
|
46
|
+
common
|
39
47
|
else
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
48
|
+
left = left.ast
|
49
|
+
left = left.expr if left.is_a?(Arel::Nodes::Grouping)
|
50
|
+
|
51
|
+
right = right.ast
|
52
|
+
right = right.expr if right.is_a?(Arel::Nodes::Grouping)
|
53
|
+
|
54
|
+
or_clause = Arel::Nodes::Or.new(left, right)
|
55
|
+
|
56
|
+
common.predicates << Arel::Nodes::Grouping.new(or_clause)
|
57
|
+
common
|
44
58
|
end
|
45
59
|
end
|
46
60
|
|
47
61
|
def to_h(table_name = nil)
|
48
|
-
equalities
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
62
|
+
equalities(predicates).each_with_object({}) do |node, hash|
|
63
|
+
next if table_name&.!= node.left.relation.name
|
64
|
+
name = node.left.name.to_s
|
65
|
+
value = extract_node_value(node.right)
|
66
|
+
hash[name] = value
|
53
67
|
end
|
54
|
-
|
55
|
-
binds = self.binds.map { |attr| [attr.name, attr.value] }.to_h
|
56
|
-
|
57
|
-
equalities.map { |node|
|
58
|
-
name = node.left.name
|
59
|
-
[name, binds.fetch(name.to_s) {
|
60
|
-
case node.right
|
61
|
-
when Array then node.right.map(&:val)
|
62
|
-
when Arel::Nodes::Casted, Arel::Nodes::Quoted
|
63
|
-
node.right.val
|
64
|
-
end
|
65
|
-
}]
|
66
|
-
}.to_h
|
67
68
|
end
|
68
69
|
|
69
70
|
def ast
|
70
|
-
|
71
|
+
predicates = predicates_with_wrapped_sql_literals
|
72
|
+
predicates.one? ? predicates.first : Arel::Nodes::And.new(predicates)
|
71
73
|
end
|
72
74
|
|
73
75
|
def ==(other)
|
74
76
|
other.is_a?(WhereClause) &&
|
75
|
-
predicates == other.predicates
|
76
|
-
binds == other.binds
|
77
|
+
predicates == other.predicates
|
77
78
|
end
|
78
79
|
|
79
80
|
def invert
|
80
|
-
|
81
|
+
if predicates.size == 1
|
82
|
+
inverted_predicates = [ invert_predicate(predicates.first) ]
|
83
|
+
else
|
84
|
+
inverted_predicates = [ Arel::Nodes::Not.new(ast) ]
|
85
|
+
end
|
86
|
+
|
87
|
+
WhereClause.new(inverted_predicates)
|
81
88
|
end
|
82
89
|
|
83
90
|
def self.empty
|
84
|
-
@empty ||= new([]
|
91
|
+
@empty ||= new([]).freeze
|
92
|
+
end
|
93
|
+
|
94
|
+
def contradiction?
|
95
|
+
predicates.any? do |x|
|
96
|
+
case x
|
97
|
+
when Arel::Nodes::In
|
98
|
+
Array === x.right && x.right.empty?
|
99
|
+
when Arel::Nodes::Equality
|
100
|
+
x.right.respond_to?(:unboundable?) && x.right.unboundable?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def extract_attributes
|
106
|
+
predicates.each_with_object([]) do |node, attrs|
|
107
|
+
attr = extract_attribute(node) || begin
|
108
|
+
node.left if node.equality? && node.left.is_a?(Arel::Predications)
|
109
|
+
end
|
110
|
+
attrs << attr if attr
|
111
|
+
end
|
85
112
|
end
|
86
113
|
|
87
114
|
protected
|
115
|
+
attr_reader :predicates
|
88
116
|
|
89
|
-
|
117
|
+
def referenced_columns
|
118
|
+
predicates.each_with_object({}) do |node, hash|
|
119
|
+
attr = extract_attribute(node) || begin
|
120
|
+
node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
|
121
|
+
end
|
90
122
|
|
91
|
-
|
92
|
-
|
93
|
-
equality_nodes = predicates.select { |n| equality_node?(n) }
|
94
|
-
Set.new(equality_nodes, &:left)
|
123
|
+
hash[attr] = node if attr
|
124
|
+
end
|
95
125
|
end
|
96
|
-
end
|
97
126
|
|
98
127
|
private
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
128
|
+
def extract_attribute(node)
|
129
|
+
attr_node = nil
|
130
|
+
Arel.fetch_attribute(node) do |attr|
|
131
|
+
return if attr_node&.!= attr # all attr nodes should be the same
|
132
|
+
attr_node = attr
|
133
|
+
end
|
134
|
+
attr_node
|
103
135
|
end
|
104
|
-
end
|
105
136
|
|
106
|
-
|
107
|
-
|
108
|
-
end
|
137
|
+
def equalities(predicates)
|
138
|
+
equalities = []
|
109
139
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
140
|
+
predicates.each do |node|
|
141
|
+
if equality_node?(node)
|
142
|
+
equalities << node
|
143
|
+
elsif node.is_a?(Arel::Nodes::And)
|
144
|
+
equalities.concat equalities(node.children)
|
145
|
+
end
|
146
|
+
end
|
115
147
|
|
116
|
-
|
117
|
-
|
118
|
-
end
|
148
|
+
equalities
|
149
|
+
end
|
119
150
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
151
|
+
def predicates_unreferenced_by(other)
|
152
|
+
referenced_columns = other.referenced_columns
|
153
|
+
|
154
|
+
predicates.reject do |node|
|
155
|
+
attr = extract_attribute(node) || begin
|
156
|
+
node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
|
157
|
+
end
|
158
|
+
next false unless attr
|
159
|
+
|
160
|
+
ref = referenced_columns[attr]
|
161
|
+
next false unless ref
|
162
|
+
|
163
|
+
if equality_node?(node) && equality_node?(ref) || node == ref
|
164
|
+
true
|
165
|
+
else
|
166
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
167
|
+
Merging (#{node.to_sql}) and (#{ref.to_sql}) no longer maintain
|
168
|
+
both conditions, and will be replaced by the latter in Rails 6.2.
|
169
|
+
To migrate to Rails 6.2's behavior, use `relation.merge(other, rewhere: true)`.
|
170
|
+
MSG
|
171
|
+
false
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def equality_node?(node)
|
177
|
+
!node.is_a?(String) && node.equality?
|
132
178
|
end
|
133
|
-
end
|
134
179
|
|
135
|
-
|
136
|
-
predicates.reject do |node|
|
180
|
+
def invert_predicate(node)
|
137
181
|
case node
|
138
|
-
when
|
139
|
-
|
140
|
-
|
182
|
+
when NilClass
|
183
|
+
raise ArgumentError, "Invalid argument for .where.not(), got nil."
|
184
|
+
when String
|
185
|
+
Arel::Nodes::Not.new(Arel::Nodes::SqlLiteral.new(node))
|
186
|
+
else
|
187
|
+
node.invert
|
141
188
|
end
|
142
189
|
end
|
143
|
-
end
|
144
190
|
|
145
|
-
|
146
|
-
|
147
|
-
columns.
|
191
|
+
def except_predicates(columns)
|
192
|
+
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
193
|
+
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
194
|
+
|
195
|
+
predicates.reject do |node|
|
196
|
+
if !non_attrs.empty? && node.equality? && node.left.is_a?(Arel::Predications)
|
197
|
+
non_attrs.include?(node.left)
|
198
|
+
end || Arel.fetch_attribute(node) do |attr|
|
199
|
+
attrs.include?(attr) || columns.include?(attr.name.to_s)
|
200
|
+
end
|
201
|
+
end
|
148
202
|
end
|
149
|
-
end
|
150
203
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
204
|
+
def predicates_with_wrapped_sql_literals
|
205
|
+
non_empty_predicates.map do |node|
|
206
|
+
case node
|
207
|
+
when Arel::Nodes::SqlLiteral, ::String
|
208
|
+
wrap_sql_literal(node)
|
209
|
+
else node
|
210
|
+
end
|
157
211
|
end
|
158
212
|
end
|
159
|
-
end
|
160
213
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
214
|
+
ARRAY_WITH_EMPTY_STRING = [""]
|
215
|
+
def non_empty_predicates
|
216
|
+
predicates - ARRAY_WITH_EMPTY_STRING
|
217
|
+
end
|
165
218
|
|
166
|
-
|
167
|
-
|
168
|
-
|
219
|
+
def wrap_sql_literal(node)
|
220
|
+
if ::String === node
|
221
|
+
node = Arel.sql(node)
|
222
|
+
end
|
223
|
+
Arel::Nodes::Grouping.new(node)
|
224
|
+
end
|
225
|
+
|
226
|
+
def extract_node_value(node)
|
227
|
+
case node
|
228
|
+
when Array
|
229
|
+
node.map { |v| extract_node_value(v) }
|
230
|
+
when Arel::Nodes::BindParam, Arel::Nodes::Casted, Arel::Nodes::Quoted
|
231
|
+
node.value_before_type_cast
|
232
|
+
end
|
169
233
|
end
|
170
|
-
Arel::Nodes::Grouping.new(node)
|
171
|
-
end
|
172
234
|
end
|
173
235
|
end
|
174
236
|
end
|
data/lib/active_record/result.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
###
|
3
5
|
# This class encapsulates a result returned from calling
|
@@ -19,7 +21,7 @@ module ActiveRecord
|
|
19
21
|
# ]
|
20
22
|
#
|
21
23
|
# # Get an array of hashes representing the result (column => value):
|
22
|
-
# result.
|
24
|
+
# result.to_a
|
23
25
|
# # => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
|
24
26
|
# {"id" => 2, "title" => "title_2", "body" => "body_2"},
|
25
27
|
# ...
|
@@ -32,8 +34,6 @@ module ActiveRecord
|
|
32
34
|
class Result
|
33
35
|
include Enumerable
|
34
36
|
|
35
|
-
IDENTITY_TYPE = Type::Value.new # :nodoc:
|
36
|
-
|
37
37
|
attr_reader :columns, :rows, :column_types
|
38
38
|
|
39
39
|
def initialize(columns, rows, column_types = {})
|
@@ -43,10 +43,20 @@ module ActiveRecord
|
|
43
43
|
@column_types = column_types
|
44
44
|
end
|
45
45
|
|
46
|
+
# Returns true if this result set includes the column named +name+
|
47
|
+
def includes_column?(name)
|
48
|
+
@columns.include? name
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the number of elements in the rows array.
|
46
52
|
def length
|
47
53
|
@rows.length
|
48
54
|
end
|
49
55
|
|
56
|
+
# Calls the given block once for each element in row collection, passing
|
57
|
+
# row as parameter.
|
58
|
+
#
|
59
|
+
# Returns an +Enumerator+ if no block is given.
|
50
60
|
def each
|
51
61
|
if block_given?
|
52
62
|
hash_rows.each { |row| yield row }
|
@@ -55,43 +65,56 @@ module ActiveRecord
|
|
55
65
|
end
|
56
66
|
end
|
57
67
|
|
58
|
-
def to_hash
|
59
|
-
hash_rows
|
60
|
-
end
|
61
|
-
|
62
68
|
alias :map! :map
|
63
69
|
alias :collect! :map
|
70
|
+
deprecate "map!": :map
|
71
|
+
deprecate "collect!": :map
|
64
72
|
|
65
|
-
# Returns true if there are no records.
|
73
|
+
# Returns true if there are no records, otherwise false.
|
66
74
|
def empty?
|
67
75
|
rows.empty?
|
68
76
|
end
|
69
77
|
|
78
|
+
# Returns an array of hashes representing each row record.
|
70
79
|
def to_ary
|
71
80
|
hash_rows
|
72
81
|
end
|
73
82
|
|
83
|
+
alias :to_a :to_ary
|
84
|
+
|
74
85
|
def [](idx)
|
75
86
|
hash_rows[idx]
|
76
87
|
end
|
77
88
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
def last
|
84
|
-
return nil if @rows.empty?
|
85
|
-
Hash[@columns.zip(@rows.last)]
|
89
|
+
# Returns the last record from the rows collection.
|
90
|
+
def last(n = nil)
|
91
|
+
n ? hash_rows.last(n) : hash_rows.last
|
86
92
|
end
|
87
93
|
|
88
94
|
def cast_values(type_overrides = {}) # :nodoc:
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
95
|
+
if columns.one?
|
96
|
+
# Separated to avoid allocating an array per row
|
97
|
+
|
98
|
+
type = if type_overrides.is_a?(Array)
|
99
|
+
type_overrides.first
|
100
|
+
else
|
101
|
+
column_type(columns.first, type_overrides)
|
102
|
+
end
|
93
103
|
|
94
|
-
|
104
|
+
rows.map do |(value)|
|
105
|
+
type.deserialize(value)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
types = if type_overrides.is_a?(Array)
|
109
|
+
type_overrides
|
110
|
+
else
|
111
|
+
columns.map { |name| column_type(name, type_overrides) }
|
112
|
+
end
|
113
|
+
|
114
|
+
rows.map do |values|
|
115
|
+
Array.new(values.size) { |i| types[i].deserialize(values[i]) }
|
116
|
+
end
|
117
|
+
end
|
95
118
|
end
|
96
119
|
|
97
120
|
def initialize_copy(other)
|
@@ -102,37 +125,51 @@ module ActiveRecord
|
|
102
125
|
end
|
103
126
|
|
104
127
|
private
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
128
|
+
def column_type(name, type_overrides = {})
|
129
|
+
type_overrides.fetch(name) do
|
130
|
+
column_types.fetch(name, Type.default_value)
|
131
|
+
end
|
109
132
|
end
|
110
|
-
end
|
111
133
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
134
|
+
def hash_rows
|
135
|
+
@hash_rows ||=
|
136
|
+
begin
|
137
|
+
# We freeze the strings to prevent them getting duped when
|
138
|
+
# used as keys in ActiveRecord::Base's @attributes hash
|
139
|
+
columns = @columns.map(&:-@)
|
140
|
+
length = columns.length
|
141
|
+
template = nil
|
142
|
+
|
143
|
+
@rows.map { |row|
|
144
|
+
if template
|
145
|
+
# We use transform_values to build subsequent rows from the
|
146
|
+
# hash of the first row. This is faster because we avoid any
|
147
|
+
# reallocs and in Ruby 2.7+ avoid hashing entirely.
|
148
|
+
index = -1
|
149
|
+
template.transform_values do
|
150
|
+
row[index += 1]
|
151
|
+
end
|
152
|
+
else
|
153
|
+
# In the past we used Hash[columns.zip(row)]
|
154
|
+
# though elegant, the verbose way is much more efficient
|
155
|
+
# both time and memory wise cause it avoids a big array allocation
|
156
|
+
# this method is called a lot and needs to be micro optimised
|
157
|
+
hash = {}
|
158
|
+
|
159
|
+
index = 0
|
160
|
+
while index < length
|
161
|
+
hash[columns[index]] = row[index]
|
162
|
+
index += 1
|
163
|
+
end
|
164
|
+
|
165
|
+
# It's possible to select the same column twice, in which case
|
166
|
+
# we can't use a template
|
167
|
+
template = hash if hash.length == length
|
168
|
+
|
169
|
+
hash
|
170
|
+
end
|
171
|
+
}
|
172
|
+
end
|
173
|
+
end
|
137
174
|
end
|
138
175
|
end
|