activerecord 5.2.3 → 6.1.0
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 +898 -532
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +5 -4
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +95 -42
- data/lib/active_record/associations/association_scope.rb +21 -21
- data/lib/active_record/associations/belongs_to_association.rb +50 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -5
- data/lib/active_record/associations/builder/association.rb +23 -21
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +10 -19
- 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 +31 -29
- 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 +27 -28
- 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 +54 -12
- 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 +71 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +48 -35
- 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 +133 -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 +45 -8
- data/lib/active_record/autosave_association.rb +76 -47
- 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 +293 -132
- 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 +21 -17
- 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 +203 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +381 -146
- data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -98
- 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 +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -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 +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -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 +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -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/money.rb +2 -2
- 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 +222 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -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 +175 -187
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +285 -33
- data/lib/active_record/core.rb +308 -100
- data/lib/active_record/counter_cache.rb +8 -30
- 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/database_configurations.rb +272 -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 +71 -17
- 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 +197 -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 +208 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +26 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +26 -22
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +34 -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 +141 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +205 -156
- 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 +115 -58
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +402 -78
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +113 -101
- 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 -93
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +65 -40
- 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 +4 -7
- 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 +58 -40
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +487 -199
- 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 +108 -58
- data/lib/active_record/relation.rb +375 -104
- 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 +6 -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 +51 -8
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -43
- data/lib/active_record/tasks/database_tasks.rb +276 -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 +246 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +59 -117
- 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 +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/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 +117 -32
- 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
| @@ -3,19 +3,13 @@ | |
| 3 3 | 
             
            module ActiveRecord
         | 
| 4 4 | 
             
              module ConnectionAdapters # :nodoc:
         | 
| 5 5 | 
             
                module DatabaseLimits
         | 
| 6 | 
            -
                   | 
| 7 | 
            -
                  def table_alias_length
         | 
| 8 | 
            -
                    255
         | 
| 9 | 
            -
                  end
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                  # Returns the maximum length of a column name.
         | 
| 12 | 
            -
                  def column_name_length
         | 
| 6 | 
            +
                  def max_identifier_length # :nodoc:
         | 
| 13 7 | 
             
                    64
         | 
| 14 8 | 
             
                  end
         | 
| 15 9 |  | 
| 16 | 
            -
                  # Returns the maximum length of a table  | 
| 17 | 
            -
                  def  | 
| 18 | 
            -
                     | 
| 10 | 
            +
                  # Returns the maximum length of a table alias.
         | 
| 11 | 
            +
                  def table_alias_length
         | 
| 12 | 
            +
                    max_identifier_length
         | 
| 19 13 | 
             
                  end
         | 
| 20 14 |  | 
| 21 15 | 
             
                  # Returns the maximum allowed length for an index name. This
         | 
| @@ -26,25 +20,11 @@ module ActiveRecord | |
| 26 20 | 
             
                  def allowed_index_name_length
         | 
| 27 21 | 
             
                    index_name_length
         | 
| 28 22 | 
             
                  end
         | 
| 23 | 
            +
                  deprecate :allowed_index_name_length
         | 
| 29 24 |  | 
| 30 25 | 
             
                  # Returns the maximum length of an index name.
         | 
| 31 26 | 
             
                  def index_name_length
         | 
| 32 | 
            -
                     | 
| 33 | 
            -
                  end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  # Returns the maximum number of columns per table.
         | 
| 36 | 
            -
                  def columns_per_table
         | 
| 37 | 
            -
                    1024
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                  # Returns the maximum number of indexes per table.
         | 
| 41 | 
            -
                  def indexes_per_table
         | 
| 42 | 
            -
                    16
         | 
| 43 | 
            -
                  end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                  # Returns the maximum number of columns in a multicolumn index.
         | 
| 46 | 
            -
                  def columns_per_multicolumn_index
         | 
| 47 | 
            -
                    16
         | 
| 27 | 
            +
                    max_identifier_length
         | 
| 48 28 | 
             
                  end
         | 
| 49 29 |  | 
| 50 30 | 
             
                  # Returns the maximum number of elements in an IN (x,y,z) clause.
         | 
| @@ -52,16 +32,7 @@ module ActiveRecord | |
| 52 32 | 
             
                  def in_clause_length
         | 
| 53 33 | 
             
                    nil
         | 
| 54 34 | 
             
                  end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                  # Returns the maximum length of an SQL query.
         | 
| 57 | 
            -
                  def sql_query_length
         | 
| 58 | 
            -
                    1048575
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  # Returns maximum number of joins in a single query.
         | 
| 62 | 
            -
                  def joins_per_query
         | 
| 63 | 
            -
                    256
         | 
| 64 | 
            -
                  end
         | 
| 35 | 
            +
                  deprecate :in_clause_length
         | 
| 65 36 |  | 
| 66 37 | 
             
                  private
         | 
| 67 38 | 
             
                    def bind_params_length
         | 
| @@ -14,29 +14,32 @@ module ActiveRecord | |
| 14 14 | 
             
                    sql
         | 
| 15 15 | 
             
                  end
         | 
| 16 16 |  | 
| 17 | 
            -
                  def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
         | 
| 17 | 
            +
                  def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil) # :nodoc:
         | 
| 18 18 | 
             
                    if arel_or_sql_string.respond_to?(:ast)
         | 
| 19 19 | 
             
                      unless binds.empty?
         | 
| 20 20 | 
             
                        raise "Passing bind parameters with an arel AST is forbidden. " \
         | 
| 21 21 | 
             
                          "The values must be stored on the AST directly"
         | 
| 22 22 | 
             
                      end
         | 
| 23 23 |  | 
| 24 | 
            +
                      collector = collector()
         | 
| 25 | 
            +
             | 
| 24 26 | 
             
                      if prepared_statements
         | 
| 25 | 
            -
                         | 
| 27 | 
            +
                        collector.preparable = true
         | 
| 28 | 
            +
                        sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
         | 
| 26 29 |  | 
| 27 30 | 
             
                        if binds.length > bind_params_length
         | 
| 28 31 | 
             
                          unprepared_statement do
         | 
| 29 | 
            -
                             | 
| 30 | 
            -
                            visitor.preparable = false
         | 
| 32 | 
            +
                            return to_sql_and_binds(arel_or_sql_string)
         | 
| 31 33 | 
             
                          end
         | 
| 32 34 | 
             
                        end
         | 
| 35 | 
            +
                        preparable = collector.preparable
         | 
| 33 36 | 
             
                      else
         | 
| 34 | 
            -
                        sql = visitor. | 
| 37 | 
            +
                        sql = visitor.compile(arel_or_sql_string.ast, collector)
         | 
| 35 38 | 
             
                      end
         | 
| 36 | 
            -
                      [sql.freeze, binds]
         | 
| 39 | 
            +
                      [sql.freeze, binds, preparable]
         | 
| 37 40 | 
             
                    else
         | 
| 38 | 
            -
                       | 
| 39 | 
            -
                      [arel_or_sql_string | 
| 41 | 
            +
                      arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
         | 
| 42 | 
            +
                      [arel_or_sql_string, binds, preparable]
         | 
| 40 43 | 
             
                    end
         | 
| 41 44 | 
             
                  end
         | 
| 42 45 | 
             
                  private :to_sql_and_binds
         | 
| @@ -45,11 +48,11 @@ module ActiveRecord | |
| 45 48 | 
             
                  # can be used to query the database repeatedly.
         | 
| 46 49 | 
             
                  def cacheable_query(klass, arel) # :nodoc:
         | 
| 47 50 | 
             
                    if prepared_statements
         | 
| 48 | 
            -
                      sql, binds = visitor. | 
| 51 | 
            +
                      sql, binds = visitor.compile(arel.ast, collector)
         | 
| 49 52 | 
             
                      query = klass.query(sql)
         | 
| 50 53 | 
             
                    else
         | 
| 51 | 
            -
                      collector =  | 
| 52 | 
            -
                      parts, binds = visitor. | 
| 54 | 
            +
                      collector = klass.partial_query_collector
         | 
| 55 | 
            +
                      parts, binds = visitor.compile(arel.ast, collector)
         | 
| 53 56 | 
             
                      query = klass.partial_query(parts)
         | 
| 54 57 | 
             
                    end
         | 
| 55 58 | 
             
                    [query, binds]
         | 
| @@ -58,17 +61,15 @@ module ActiveRecord | |
| 58 61 | 
             
                  # Returns an ActiveRecord::Result instance.
         | 
| 59 62 | 
             
                  def select_all(arel, name = nil, binds = [], preparable: nil)
         | 
| 60 63 | 
             
                    arel = arel_from_relation(arel)
         | 
| 61 | 
            -
                    sql, binds = to_sql_and_binds(arel, binds)
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                    if preparable.nil?
         | 
| 64 | 
            -
                      preparable = prepared_statements ? visitor.preparable : false
         | 
| 65 | 
            -
                    end
         | 
| 64 | 
            +
                    sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
         | 
| 66 65 |  | 
| 67 66 | 
             
                    if prepared_statements && preparable
         | 
| 68 67 | 
             
                      select_prepared(sql, name, binds)
         | 
| 69 68 | 
             
                    else
         | 
| 70 69 | 
             
                      select(sql, name, binds)
         | 
| 71 70 | 
             
                    end
         | 
| 71 | 
            +
                  rescue ::RangeError
         | 
| 72 | 
            +
                    ActiveRecord::Result.new([], [])
         | 
| 72 73 | 
             
                  end
         | 
| 73 74 |  | 
| 74 75 | 
             
                  # Returns a record hash with the column names as keys and column values
         | 
| @@ -106,6 +107,11 @@ module ActiveRecord | |
| 106 107 | 
             
                    exec_query(sql, name).rows
         | 
| 107 108 | 
             
                  end
         | 
| 108 109 |  | 
| 110 | 
            +
                  # Determines whether the SQL statement is a write query.
         | 
| 111 | 
            +
                  def write_query?(sql)
         | 
| 112 | 
            +
                    raise NotImplementedError
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
             | 
| 109 115 | 
             
                  # Executes the SQL statement in the context of this connection and returns
         | 
| 110 116 | 
             
                  # the raw result from the connection adapter.
         | 
| 111 117 | 
             
                  # Note: depending on your database connector, the result returned by this
         | 
| @@ -126,7 +132,7 @@ module ActiveRecord | |
| 126 132 | 
             
                  # +binds+ as the bind substitutes. +name+ is logged along with
         | 
| 127 133 | 
             
                  # the executed +sql+ statement.
         | 
| 128 134 | 
             
                  def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
         | 
| 129 | 
            -
                    sql, binds = sql_for_insert(sql, pk,  | 
| 135 | 
            +
                    sql, binds = sql_for_insert(sql, pk, binds)
         | 
| 130 136 | 
             
                    exec_query(sql, name, binds)
         | 
| 131 137 | 
             
                  end
         | 
| 132 138 |  | 
| @@ -137,11 +143,6 @@ module ActiveRecord | |
| 137 143 | 
             
                    exec_query(sql, name, binds)
         | 
| 138 144 | 
             
                  end
         | 
| 139 145 |  | 
| 140 | 
            -
                  # Executes the truncate statement.
         | 
| 141 | 
            -
                  def truncate(table_name, name = nil)
         | 
| 142 | 
            -
                    raise NotImplementedError
         | 
| 143 | 
            -
                  end
         | 
| 144 | 
            -
             | 
| 145 146 | 
             
                  # Executes update +sql+ statement in the context of this connection using
         | 
| 146 147 | 
             
                  # +binds+ as the bind substitutes. +name+ is logged along with
         | 
| 147 148 | 
             
                  # the executed +sql+ statement.
         | 
| @@ -149,6 +150,14 @@ module ActiveRecord | |
| 149 150 | 
             
                    exec_query(sql, name, binds)
         | 
| 150 151 | 
             
                  end
         | 
| 151 152 |  | 
| 153 | 
            +
                  def exec_insert_all(sql, name) # :nodoc:
         | 
| 154 | 
            +
                    exec_query(sql, name)
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                  def explain(arel, binds = []) # :nodoc:
         | 
| 158 | 
            +
                    raise NotImplementedError
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
             | 
| 152 161 | 
             
                  # Executes an INSERT query and returns the new record's ID
         | 
| 153 162 | 
             
                  #
         | 
| 154 163 | 
             
                  # +id_value+ will be returned unless the value is +nil+, in
         | 
| @@ -176,27 +185,53 @@ module ActiveRecord | |
| 176 185 | 
             
                    exec_delete(sql, name, binds)
         | 
| 177 186 | 
             
                  end
         | 
| 178 187 |  | 
| 179 | 
            -
                  #  | 
| 180 | 
            -
                   | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 188 | 
            +
                  # Executes the truncate statement.
         | 
| 189 | 
            +
                  def truncate(table_name, name = nil)
         | 
| 190 | 
            +
                    execute(build_truncate_statement(table_name), name)
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                  def truncate_tables(*table_names) # :nodoc:
         | 
| 194 | 
            +
                    table_names -= [schema_migration.table_name, InternalMetadata.table_name]
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                    return if table_names.empty?
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                    with_multi_statements do
         | 
| 199 | 
            +
                      disable_referential_integrity do
         | 
| 200 | 
            +
                        statements = build_truncate_statements(table_names)
         | 
| 201 | 
            +
                        execute_batch(statements, "Truncate Tables")
         | 
| 202 | 
            +
                      end
         | 
| 203 | 
            +
                    end
         | 
| 183 204 | 
             
                  end
         | 
| 184 | 
            -
                  deprecate :supports_statement_cache?
         | 
| 185 205 |  | 
| 186 206 | 
             
                  # Runs the given block in a database transaction, and returns the result
         | 
| 187 207 | 
             
                  # of the block.
         | 
| 188 208 | 
             
                  #
         | 
| 189 209 | 
             
                  # == Nested transactions support
         | 
| 190 210 | 
             
                  #
         | 
| 211 | 
            +
                  # #transaction calls can be nested. By default, this makes all database
         | 
| 212 | 
            +
                  # statements in the nested transaction block become part of the parent
         | 
| 213 | 
            +
                  # transaction. For example, the following behavior may be surprising:
         | 
| 214 | 
            +
                  #
         | 
| 215 | 
            +
                  #   ActiveRecord::Base.transaction do
         | 
| 216 | 
            +
                  #     Post.create(title: 'first')
         | 
| 217 | 
            +
                  #     ActiveRecord::Base.transaction do
         | 
| 218 | 
            +
                  #       Post.create(title: 'second')
         | 
| 219 | 
            +
                  #       raise ActiveRecord::Rollback
         | 
| 220 | 
            +
                  #     end
         | 
| 221 | 
            +
                  #   end
         | 
| 222 | 
            +
                  #
         | 
| 223 | 
            +
                  # This creates both "first" and "second" posts. Reason is the
         | 
| 224 | 
            +
                  # ActiveRecord::Rollback exception in the nested block does not issue a
         | 
| 225 | 
            +
                  # ROLLBACK. Since these exceptions are captured in transaction blocks,
         | 
| 226 | 
            +
                  # the parent block does not see it and the real transaction is committed.
         | 
| 227 | 
            +
                  #
         | 
| 191 228 | 
             
                  # Most databases don't support true nested transactions. At the time of
         | 
| 192 229 | 
             
                  # writing, the only database that supports true nested transactions that
         | 
| 193 230 | 
             
                  # we're aware of, is MS-SQL.
         | 
| 194 231 | 
             
                  #
         | 
| 195 232 | 
             
                  # In order to get around this problem, #transaction will emulate the effect
         | 
| 196 233 | 
             
                  # of nested transactions, by using savepoints:
         | 
| 197 | 
            -
                  # https://dev.mysql.com/doc/refman/ | 
| 198 | 
            -
                  # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
         | 
| 199 | 
            -
                  # supports savepoints.
         | 
| 234 | 
            +
                  # https://dev.mysql.com/doc/refman/en/savepoint.html.
         | 
| 200 235 | 
             
                  #
         | 
| 201 236 | 
             
                  # It is safe to call this method if a database transaction is already open,
         | 
| 202 237 | 
             
                  # i.e. if #transaction is called within another #transaction block. In case
         | 
| @@ -208,6 +243,24 @@ module ActiveRecord | |
| 208 243 | 
             
                  # - However, if +:requires_new+ is set, the block will be wrapped in a
         | 
| 209 244 | 
             
                  #   database savepoint acting as a sub-transaction.
         | 
| 210 245 | 
             
                  #
         | 
| 246 | 
            +
                  # In order to get a ROLLBACK for the nested transaction you may ask for a
         | 
| 247 | 
            +
                  # real sub-transaction by passing <tt>requires_new: true</tt>.
         | 
| 248 | 
            +
                  # If anything goes wrong, the database rolls back to the beginning of
         | 
| 249 | 
            +
                  # the sub-transaction without rolling back the parent transaction.
         | 
| 250 | 
            +
                  # If we add it to the previous example:
         | 
| 251 | 
            +
                  #
         | 
| 252 | 
            +
                  #   ActiveRecord::Base.transaction do
         | 
| 253 | 
            +
                  #     Post.create(title: 'first')
         | 
| 254 | 
            +
                  #     ActiveRecord::Base.transaction(requires_new: true) do
         | 
| 255 | 
            +
                  #       Post.create(title: 'second')
         | 
| 256 | 
            +
                  #       raise ActiveRecord::Rollback
         | 
| 257 | 
            +
                  #     end
         | 
| 258 | 
            +
                  #   end
         | 
| 259 | 
            +
                  #
         | 
| 260 | 
            +
                  # only post with title "first" is created.
         | 
| 261 | 
            +
                  #
         | 
| 262 | 
            +
                  # See ActiveRecord::Transactions to learn more.
         | 
| 263 | 
            +
                  #
         | 
| 211 264 | 
             
                  # === Caveats
         | 
| 212 265 | 
             
                  #
         | 
| 213 266 | 
             
                  # MySQL doesn't support DDL transactions. If you perform a DDL operation,
         | 
| @@ -247,7 +300,7 @@ module ActiveRecord | |
| 247 300 | 
             
                  # semantics of these different levels:
         | 
| 248 301 | 
             
                  #
         | 
| 249 302 | 
             
                  # * https://www.postgresql.org/docs/current/static/transaction-iso.html
         | 
| 250 | 
            -
                  # * https://dev.mysql.com/doc/refman/ | 
| 303 | 
            +
                  # * https://dev.mysql.com/doc/refman/en/set-transaction.html
         | 
| 251 304 | 
             
                  #
         | 
| 252 305 | 
             
                  # An ActiveRecord::TransactionIsolationError will be raised if:
         | 
| 253 306 | 
             
                  #
         | 
| @@ -272,7 +325,16 @@ module ActiveRecord | |
| 272 325 |  | 
| 273 326 | 
             
                  attr_reader :transaction_manager #:nodoc:
         | 
| 274 327 |  | 
| 275 | 
            -
                  delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction, | 
| 328 | 
            +
                  delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
         | 
| 329 | 
            +
                           :commit_transaction, :rollback_transaction, :materialize_transactions,
         | 
| 330 | 
            +
                           :disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                  def mark_transaction_written_if_write(sql) # :nodoc:
         | 
| 333 | 
            +
                    transaction = current_transaction
         | 
| 334 | 
            +
                    if transaction.open?
         | 
| 335 | 
            +
                      transaction.written ||= write_query?(sql)
         | 
| 336 | 
            +
                    end
         | 
| 337 | 
            +
                  end
         | 
| 276 338 |  | 
| 277 339 | 
             
                  def transaction_open?
         | 
| 278 340 | 
             
                    current_transaction.open?
         | 
| @@ -284,12 +346,8 @@ module ActiveRecord | |
| 284 346 |  | 
| 285 347 | 
             
                  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
         | 
| 286 348 | 
             
                  # can be called.
         | 
| 287 | 
            -
                  def add_transaction_record(record)
         | 
| 288 | 
            -
                    current_transaction.add_record(record)
         | 
| 289 | 
            -
                  end
         | 
| 290 | 
            -
             | 
| 291 | 
            -
                  def transaction_state
         | 
| 292 | 
            -
                    current_transaction.state
         | 
| 349 | 
            +
                  def add_transaction_record(record, ensure_finalize = true)
         | 
| 350 | 
            +
                    current_transaction.add_record(record, ensure_finalize)
         | 
| 293 351 | 
             
                  end
         | 
| 294 352 |  | 
| 295 353 | 
             
                  # Begins the transaction (and turns off auto-committing).
         | 
| @@ -336,69 +394,29 @@ module ActiveRecord | |
| 336 394 | 
             
                  end
         | 
| 337 395 |  | 
| 338 396 | 
             
                  # Inserts the given fixture into the table. Overridden in adapters that require
         | 
| 339 | 
            -
                  # something beyond a simple insert ( | 
| 340 | 
            -
                  # Most of adapters should implement ` | 
| 397 | 
            +
                  # something beyond a simple insert (e.g. Oracle).
         | 
| 398 | 
            +
                  # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
         | 
| 341 399 | 
             
                  # We keep this method to provide fallback
         | 
| 342 400 | 
             
                  # for databases like sqlite that do not support bulk inserts.
         | 
| 343 401 | 
             
                  def insert_fixture(fixture, table_name)
         | 
| 344 | 
            -
                    fixture  | 
| 345 | 
            -
             | 
| 346 | 
            -
                    columns = schema_cache.columns_hash(table_name)
         | 
| 347 | 
            -
                    binds = fixture.map do |name, value|
         | 
| 348 | 
            -
                      if column = columns[name]
         | 
| 349 | 
            -
                        type = lookup_cast_type_from_column(column)
         | 
| 350 | 
            -
                        Relation::QueryAttribute.new(name, value, type)
         | 
| 351 | 
            -
                      else
         | 
| 352 | 
            -
                        raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
         | 
| 353 | 
            -
                      end
         | 
| 354 | 
            -
                    end
         | 
| 355 | 
            -
             | 
| 356 | 
            -
                    table = Arel::Table.new(table_name)
         | 
| 357 | 
            -
             | 
| 358 | 
            -
                    values = binds.map do |bind|
         | 
| 359 | 
            -
                      value = with_yaml_fallback(bind.value_for_database)
         | 
| 360 | 
            -
                      [table[bind.name], value]
         | 
| 361 | 
            -
                    end
         | 
| 362 | 
            -
             | 
| 363 | 
            -
                    manager = Arel::InsertManager.new
         | 
| 364 | 
            -
                    manager.into(table)
         | 
| 365 | 
            -
                    manager.insert(values)
         | 
| 366 | 
            -
                    execute manager.to_sql, "Fixture Insert"
         | 
| 367 | 
            -
                  end
         | 
| 368 | 
            -
             | 
| 369 | 
            -
                  # Inserts a set of fixtures into the table. Overridden in adapters that require
         | 
| 370 | 
            -
                  # something beyond a simple insert (eg. Oracle).
         | 
| 371 | 
            -
                  def insert_fixtures(fixtures, table_name)
         | 
| 372 | 
            -
                    ActiveSupport::Deprecation.warn(<<-MSG.squish)
         | 
| 373 | 
            -
                      `insert_fixtures` is deprecated and will be removed in the next version of Rails.
         | 
| 374 | 
            -
                      Consider using `insert_fixtures_set` for performance improvement.
         | 
| 375 | 
            -
                    MSG
         | 
| 376 | 
            -
                    return if fixtures.empty?
         | 
| 377 | 
            -
             | 
| 378 | 
            -
                    execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
         | 
| 402 | 
            +
                    execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
         | 
| 379 403 | 
             
                  end
         | 
| 380 404 |  | 
| 381 405 | 
             
                  def insert_fixtures_set(fixture_set, tables_to_delete = [])
         | 
| 382 | 
            -
                    fixture_inserts = fixture_set | 
| 383 | 
            -
             | 
| 384 | 
            -
             | 
| 385 | 
            -
             | 
| 386 | 
            -
                     | 
| 387 | 
            -
             | 
| 388 | 
            -
             | 
| 389 | 
            -
             | 
| 390 | 
            -
             | 
| 391 | 
            -
                    disable_referential_integrity do
         | 
| 392 | 
            -
                      transaction(requires_new: true) do
         | 
| 393 | 
            -
                        total_sql.each do |sql|
         | 
| 394 | 
            -
                          execute sql, "Fixtures Load"
         | 
| 395 | 
            -
                          yield if block_given?
         | 
| 406 | 
            +
                    fixture_inserts = build_fixture_statements(fixture_set)
         | 
| 407 | 
            +
                    table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
         | 
| 408 | 
            +
                    statements = table_deletes + fixture_inserts
         | 
| 409 | 
            +
             | 
| 410 | 
            +
                    with_multi_statements do
         | 
| 411 | 
            +
                      disable_referential_integrity do
         | 
| 412 | 
            +
                        transaction(requires_new: true) do
         | 
| 413 | 
            +
                          execute_batch(statements, "Fixtures Load")
         | 
| 396 414 | 
             
                        end
         | 
| 397 415 | 
             
                      end
         | 
| 398 416 | 
             
                    end
         | 
| 399 417 | 
             
                  end
         | 
| 400 418 |  | 
| 401 | 
            -
                  def empty_insert_statement_value
         | 
| 419 | 
            +
                  def empty_insert_statement_value(primary_key = nil)
         | 
| 402 420 | 
             
                    "DEFAULT VALUES"
         | 
| 403 421 | 
             
                  end
         | 
| 404 422 |  | 
| @@ -416,25 +434,35 @@ module ActiveRecord | |
| 416 434 | 
             
                    end
         | 
| 417 435 | 
             
                  end
         | 
| 418 436 |  | 
| 419 | 
            -
                  #  | 
| 420 | 
            -
                  #  | 
| 421 | 
            -
                  #  | 
| 422 | 
            -
                  def  | 
| 423 | 
            -
                     | 
| 424 | 
            -
             | 
| 425 | 
            -
                     | 
| 437 | 
            +
                  # Fixture value is quoted by Arel, however scalar values
         | 
| 438 | 
            +
                  # are not quotable. In this case we want to convert
         | 
| 439 | 
            +
                  # the column value to YAML.
         | 
| 440 | 
            +
                  def with_yaml_fallback(value) # :nodoc:
         | 
| 441 | 
            +
                    if value.is_a?(Hash) || value.is_a?(Array)
         | 
| 442 | 
            +
                      YAML.dump(value)
         | 
| 443 | 
            +
                    else
         | 
| 444 | 
            +
                      value
         | 
| 445 | 
            +
                    end
         | 
| 426 446 | 
             
                  end
         | 
| 427 | 
            -
                  alias join_to_delete join_to_update
         | 
| 428 447 |  | 
| 429 448 | 
             
                  private
         | 
| 449 | 
            +
                    def execute_batch(statements, name = nil)
         | 
| 450 | 
            +
                      statements.each do |statement|
         | 
| 451 | 
            +
                        execute(statement, name)
         | 
| 452 | 
            +
                      end
         | 
| 453 | 
            +
                    end
         | 
| 454 | 
            +
             | 
| 455 | 
            +
                    DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
         | 
| 456 | 
            +
                    private_constant :DEFAULT_INSERT_VALUE
         | 
| 457 | 
            +
             | 
| 430 458 | 
             
                    def default_insert_value(column)
         | 
| 431 | 
            -
                       | 
| 459 | 
            +
                      DEFAULT_INSERT_VALUE
         | 
| 432 460 | 
             
                    end
         | 
| 433 461 |  | 
| 434 462 | 
             
                    def build_fixture_sql(fixtures, table_name)
         | 
| 435 463 | 
             
                      columns = schema_cache.columns_hash(table_name)
         | 
| 436 464 |  | 
| 437 | 
            -
                       | 
| 465 | 
            +
                      values_list = fixtures.map do |fixture|
         | 
| 438 466 | 
             
                        fixture = fixture.stringify_keys
         | 
| 439 467 |  | 
| 440 468 | 
             
                        unknown_columns = fixture.keys - columns.keys
         | 
| @@ -445,8 +473,7 @@ module ActiveRecord | |
| 445 473 | 
             
                        columns.map do |name, column|
         | 
| 446 474 | 
             
                          if fixture.key?(name)
         | 
| 447 475 | 
             
                            type = lookup_cast_type_from_column(column)
         | 
| 448 | 
            -
                             | 
| 449 | 
            -
                            with_yaml_fallback(bind.value_for_database)
         | 
| 476 | 
            +
                            with_yaml_fallback(type.serialize(fixture[name]))
         | 
| 450 477 | 
             
                          else
         | 
| 451 478 | 
             
                            default_insert_value(column)
         | 
| 452 479 | 
             
                          end
         | 
| @@ -456,21 +483,48 @@ module ActiveRecord | |
| 456 483 | 
             
                      table = Arel::Table.new(table_name)
         | 
| 457 484 | 
             
                      manager = Arel::InsertManager.new
         | 
| 458 485 | 
             
                      manager.into(table)
         | 
| 459 | 
            -
                      columns.each_key { |column| manager.columns << table[column] }
         | 
| 460 | 
            -
                      manager.values = manager.create_values_list(values)
         | 
| 461 486 |  | 
| 462 | 
            -
                       | 
| 487 | 
            +
                      if values_list.size == 1
         | 
| 488 | 
            +
                        values = values_list.shift
         | 
| 489 | 
            +
                        new_values = []
         | 
| 490 | 
            +
                        columns.each_key.with_index { |column, i|
         | 
| 491 | 
            +
                          unless values[i].equal?(DEFAULT_INSERT_VALUE)
         | 
| 492 | 
            +
                            new_values << values[i]
         | 
| 493 | 
            +
                            manager.columns << table[column]
         | 
| 494 | 
            +
                          end
         | 
| 495 | 
            +
                        }
         | 
| 496 | 
            +
                        values_list << new_values
         | 
| 497 | 
            +
                      else
         | 
| 498 | 
            +
                        columns.each_key { |column| manager.columns << table[column] }
         | 
| 499 | 
            +
                      end
         | 
| 500 | 
            +
             | 
| 501 | 
            +
                      manager.values = manager.create_values_list(values_list)
         | 
| 502 | 
            +
                      visitor.compile(manager.ast)
         | 
| 463 503 | 
             
                    end
         | 
| 464 504 |  | 
| 465 | 
            -
                    def  | 
| 466 | 
            -
                       | 
| 505 | 
            +
                    def build_fixture_statements(fixture_set)
         | 
| 506 | 
            +
                      fixture_set.map do |table_name, fixtures|
         | 
| 507 | 
            +
                        next if fixtures.empty?
         | 
| 508 | 
            +
                        build_fixture_sql(fixtures, table_name)
         | 
| 509 | 
            +
                      end.compact
         | 
| 510 | 
            +
                    end
         | 
| 511 | 
            +
             | 
| 512 | 
            +
                    def build_truncate_statement(table_name)
         | 
| 513 | 
            +
                      "TRUNCATE TABLE #{quote_table_name(table_name)}"
         | 
| 514 | 
            +
                    end
         | 
| 515 | 
            +
             | 
| 516 | 
            +
                    def build_truncate_statements(table_names)
         | 
| 517 | 
            +
                      table_names.map do |table_name|
         | 
| 518 | 
            +
                        build_truncate_statement(table_name)
         | 
| 519 | 
            +
                      end
         | 
| 467 520 | 
             
                    end
         | 
| 468 521 |  | 
| 469 | 
            -
                     | 
| 470 | 
            -
             | 
| 471 | 
            -
             | 
| 472 | 
            -
             | 
| 473 | 
            -
             | 
| 522 | 
            +
                    def with_multi_statements
         | 
| 523 | 
            +
                      yield
         | 
| 524 | 
            +
                    end
         | 
| 525 | 
            +
             | 
| 526 | 
            +
                    def combine_multi_statements(total_sql)
         | 
| 527 | 
            +
                      total_sql.join(";\n")
         | 
| 474 528 | 
             
                    end
         | 
| 475 529 |  | 
| 476 530 | 
             
                    # Returns an ActiveRecord::Result instance.
         | 
| @@ -482,7 +536,7 @@ module ActiveRecord | |
| 482 536 | 
             
                      exec_query(sql, name, binds, prepare: true)
         | 
| 483 537 | 
             
                    end
         | 
| 484 538 |  | 
| 485 | 
            -
                    def sql_for_insert(sql, pk,  | 
| 539 | 
            +
                    def sql_for_insert(sql, pk, binds)
         | 
| 486 540 | 
             
                      [sql, binds]
         | 
| 487 541 | 
             
                    end
         | 
| 488 542 |  | 
| @@ -502,39 +556,6 @@ module ActiveRecord | |
| 502 556 | 
             
                        relation
         | 
| 503 557 | 
             
                      end
         | 
| 504 558 | 
             
                    end
         | 
| 505 | 
            -
             | 
| 506 | 
            -
                    # Fixture value is quoted by Arel, however scalar values
         | 
| 507 | 
            -
                    # are not quotable. In this case we want to convert
         | 
| 508 | 
            -
                    # the column value to YAML.
         | 
| 509 | 
            -
                    def with_yaml_fallback(value)
         | 
| 510 | 
            -
                      if value.is_a?(Hash) || value.is_a?(Array)
         | 
| 511 | 
            -
                        YAML.dump(value)
         | 
| 512 | 
            -
                      else
         | 
| 513 | 
            -
                        value
         | 
| 514 | 
            -
                      end
         | 
| 515 | 
            -
                    end
         | 
| 516 | 
            -
             | 
| 517 | 
            -
                    class PartialQueryCollector
         | 
| 518 | 
            -
                      def initialize
         | 
| 519 | 
            -
                        @parts = []
         | 
| 520 | 
            -
                        @binds = []
         | 
| 521 | 
            -
                      end
         | 
| 522 | 
            -
             | 
| 523 | 
            -
                      def <<(str)
         | 
| 524 | 
            -
                        @parts << str
         | 
| 525 | 
            -
                        self
         | 
| 526 | 
            -
                      end
         | 
| 527 | 
            -
             | 
| 528 | 
            -
                      def add_bind(obj)
         | 
| 529 | 
            -
                        @binds << obj
         | 
| 530 | 
            -
                        @parts << Arel::Nodes::BindParam.new(1)
         | 
| 531 | 
            -
                        self
         | 
| 532 | 
            -
                      end
         | 
| 533 | 
            -
             | 
| 534 | 
            -
                      def value
         | 
| 535 | 
            -
                        [@parts, @binds]
         | 
| 536 | 
            -
                      end
         | 
| 537 | 
            -
                    end
         | 
| 538 559 | 
             
                end
         | 
| 539 560 | 
             
              end
         | 
| 540 561 | 
             
            end
         | 
| @@ -7,7 +7,8 @@ module ActiveRecord | |
| 7 7 | 
             
                module QueryCache
         | 
| 8 8 | 
             
                  class << self
         | 
| 9 9 | 
             
                    def included(base) #:nodoc:
         | 
| 10 | 
            -
                      dirties_query_cache base, :insert, :update, :delete, : | 
| 10 | 
            +
                      dirties_query_cache base, :insert, :update, :delete, :truncate, :truncate_tables,
         | 
| 11 | 
            +
                        :rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
         | 
| 11 12 |  | 
| 12 13 | 
             
                      base.set_callback :checkout, :after, :configure_query_cache!
         | 
| 13 14 | 
             
                      base.set_callback :checkin, :after, :disable_query_cache!
         | 
| @@ -17,7 +18,7 @@ module ActiveRecord | |
| 17 18 | 
             
                      method_names.each do |method_name|
         | 
| 18 19 | 
             
                        base.class_eval <<-end_code, __FILE__, __LINE__ + 1
         | 
| 19 20 | 
             
                          def #{method_name}(*)
         | 
| 20 | 
            -
                             | 
| 21 | 
            +
                            ActiveRecord::Base.clear_query_caches_for_current_thread
         | 
| 21 22 | 
             
                            super
         | 
| 22 23 | 
             
                          end
         | 
| 23 24 | 
             
                        end_code
         | 
| @@ -32,17 +33,17 @@ module ActiveRecord | |
| 32 33 | 
             
                    end
         | 
| 33 34 |  | 
| 34 35 | 
             
                    def enable_query_cache!
         | 
| 35 | 
            -
                      @query_cache_enabled[connection_cache_key( | 
| 36 | 
            +
                      @query_cache_enabled[connection_cache_key(current_thread)] = true
         | 
| 36 37 | 
             
                      connection.enable_query_cache! if active_connection?
         | 
| 37 38 | 
             
                    end
         | 
| 38 39 |  | 
| 39 40 | 
             
                    def disable_query_cache!
         | 
| 40 | 
            -
                      @query_cache_enabled.delete connection_cache_key( | 
| 41 | 
            +
                      @query_cache_enabled.delete connection_cache_key(current_thread)
         | 
| 41 42 | 
             
                      connection.disable_query_cache! if active_connection?
         | 
| 42 43 | 
             
                    end
         | 
| 43 44 |  | 
| 44 45 | 
             
                    def query_cache_enabled
         | 
| 45 | 
            -
                      @query_cache_enabled[connection_cache_key( | 
| 46 | 
            +
                      @query_cache_enabled[connection_cache_key(current_thread)]
         | 
| 46 47 | 
             
                    end
         | 
| 47 48 | 
             
                  end
         | 
| 48 49 |  | 
| @@ -95,11 +96,7 @@ module ActiveRecord | |
| 95 96 | 
             
                  def select_all(arel, name = nil, binds = [], preparable: nil)
         | 
| 96 97 | 
             
                    if @query_cache_enabled && !locked?(arel)
         | 
| 97 98 | 
             
                      arel = arel_from_relation(arel)
         | 
| 98 | 
            -
                      sql, binds = to_sql_and_binds(arel, binds)
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                      if preparable.nil?
         | 
| 101 | 
            -
                        preparable = prepared_statements ? visitor.preparable : false
         | 
| 102 | 
            -
                      end
         | 
| 99 | 
            +
                      sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
         | 
| 103 100 |  | 
| 104 101 | 
             
                      cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
         | 
| 105 102 | 
             
                    else
         | 
| @@ -108,19 +105,13 @@ module ActiveRecord | |
| 108 105 | 
             
                  end
         | 
| 109 106 |  | 
| 110 107 | 
             
                  private
         | 
| 111 | 
            -
             | 
| 112 108 | 
             
                    def cache_sql(sql, name, binds)
         | 
| 113 109 | 
             
                      @lock.synchronize do
         | 
| 114 110 | 
             
                        result =
         | 
| 115 111 | 
             
                          if @query_cache[sql].key?(binds)
         | 
| 116 112 | 
             
                            ActiveSupport::Notifications.instrument(
         | 
| 117 113 | 
             
                              "sql.active_record",
         | 
| 118 | 
            -
                              sql | 
| 119 | 
            -
                              binds: binds,
         | 
| 120 | 
            -
                              type_casted_binds: -> { type_casted_binds(binds) },
         | 
| 121 | 
            -
                              name: name,
         | 
| 122 | 
            -
                              connection_id: object_id,
         | 
| 123 | 
            -
                              cached: true,
         | 
| 114 | 
            +
                              cache_notification_info(sql, name, binds)
         | 
| 124 115 | 
             
                            )
         | 
| 125 116 | 
             
                            @query_cache[sql][binds]
         | 
| 126 117 | 
             
                          else
         | 
| @@ -130,6 +121,19 @@ module ActiveRecord | |
| 130 121 | 
             
                      end
         | 
| 131 122 | 
             
                    end
         | 
| 132 123 |  | 
| 124 | 
            +
                    # Database adapters can override this method to
         | 
| 125 | 
            +
                    # provide custom cache information.
         | 
| 126 | 
            +
                    def cache_notification_info(sql, name, binds)
         | 
| 127 | 
            +
                      {
         | 
| 128 | 
            +
                        sql: sql,
         | 
| 129 | 
            +
                        binds: binds,
         | 
| 130 | 
            +
                        type_casted_binds: -> { type_casted_binds(binds) },
         | 
| 131 | 
            +
                        name: name,
         | 
| 132 | 
            +
                        connection: self,
         | 
| 133 | 
            +
                        cached: true
         | 
| 134 | 
            +
                      }
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
             | 
| 133 137 | 
             
                    # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
         | 
| 134 138 | 
             
                    # queries should not be cached.
         | 
| 135 139 | 
             
                    def locked?(arel)
         |