activerecord 4.2.11.3 → 5.0.7.2
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 +1638 -1132
 - data/MIT-LICENSE +2 -2
 - data/README.rdoc +7 -8
 - data/examples/performance.rb +2 -3
 - data/examples/simple.rb +0 -1
 - data/lib/active_record.rb +7 -2
 - data/lib/active_record/aggregations.rb +34 -21
 - data/lib/active_record/association_relation.rb +7 -4
 - data/lib/active_record/associations.rb +347 -218
 - data/lib/active_record/associations/alias_tracker.rb +19 -16
 - data/lib/active_record/associations/association.rb +22 -10
 - data/lib/active_record/associations/association_scope.rb +75 -104
 - data/lib/active_record/associations/belongs_to_association.rb +21 -32
 - data/lib/active_record/associations/builder/association.rb +28 -34
 - data/lib/active_record/associations/builder/belongs_to.rb +43 -18
 - data/lib/active_record/associations/builder/collection_association.rb +7 -19
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +16 -11
 - data/lib/active_record/associations/builder/has_many.rb +4 -4
 - data/lib/active_record/associations/builder/has_one.rb +11 -6
 - data/lib/active_record/associations/builder/singular_association.rb +13 -11
 - data/lib/active_record/associations/collection_association.rb +85 -69
 - data/lib/active_record/associations/collection_proxy.rb +104 -46
 - data/lib/active_record/associations/foreign_association.rb +1 -1
 - data/lib/active_record/associations/has_many_association.rb +21 -78
 - data/lib/active_record/associations/has_many_through_association.rb +6 -47
 - data/lib/active_record/associations/has_one_association.rb +12 -5
 - data/lib/active_record/associations/join_dependency.rb +38 -22
 - data/lib/active_record/associations/join_dependency/join_association.rb +15 -14
 - data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
 - data/lib/active_record/associations/preloader.rb +14 -4
 - data/lib/active_record/associations/preloader/association.rb +52 -71
 - data/lib/active_record/associations/preloader/collection_association.rb +0 -7
 - data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
 - data/lib/active_record/associations/preloader/has_one.rb +0 -8
 - data/lib/active_record/associations/preloader/singular_association.rb +0 -1
 - data/lib/active_record/associations/preloader/through_association.rb +36 -17
 - data/lib/active_record/associations/singular_association.rb +13 -1
 - data/lib/active_record/associations/through_association.rb +12 -4
 - data/lib/active_record/attribute.rb +69 -19
 - data/lib/active_record/attribute/user_provided_default.rb +28 -0
 - data/lib/active_record/attribute_assignment.rb +19 -140
 - data/lib/active_record/attribute_decorators.rb +6 -5
 - data/lib/active_record/attribute_methods.rb +69 -44
 - data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
 - data/lib/active_record/attribute_methods/dirty.rb +46 -86
 - data/lib/active_record/attribute_methods/primary_key.rb +16 -3
 - data/lib/active_record/attribute_methods/query.rb +2 -2
 - data/lib/active_record/attribute_methods/read.rb +31 -59
 - data/lib/active_record/attribute_methods/serialization.rb +13 -16
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
 - data/lib/active_record/attribute_methods/write.rb +13 -37
 - data/lib/active_record/attribute_mutation_tracker.rb +70 -0
 - data/lib/active_record/attribute_set.rb +32 -3
 - data/lib/active_record/attribute_set/builder.rb +42 -16
 - data/lib/active_record/attributes.rb +199 -81
 - data/lib/active_record/autosave_association.rb +54 -17
 - data/lib/active_record/base.rb +32 -23
 - data/lib/active_record/callbacks.rb +39 -43
 - data/lib/active_record/coders/json.rb +1 -1
 - data/lib/active_record/coders/yaml_column.rb +20 -8
 - data/lib/active_record/collection_cache_key.rb +50 -0
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +467 -189
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -62
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +39 -4
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +86 -13
 - data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
 - data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -188
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +407 -156
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -71
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +433 -399
 - data/lib/active_record/connection_adapters/column.rb +28 -43
 - data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
 - data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
 - data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
 - data/lib/active_record/connection_adapters/mysql/database_statements.rb +108 -0
 - data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
 - data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
 - data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
 - data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
 - data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
 - data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -166
 - data/lib/active_record/connection_adapters/postgresql/column.rb +33 -11
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -72
 - data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
 - data/lib/active_record/connection_adapters/postgresql/oid/array.rb +37 -57
 - data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +3 -3
 - data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
 - data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +13 -3
 - data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
 - data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
 - data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +56 -19
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
 - data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
 - data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +250 -154
 - data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
 - data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +264 -170
 - data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
 - data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
 - data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
 - data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
 - data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +151 -194
 - data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
 - data/lib/active_record/connection_handling.rb +37 -14
 - data/lib/active_record/core.rb +92 -108
 - data/lib/active_record/counter_cache.rb +13 -24
 - data/lib/active_record/dynamic_matchers.rb +1 -20
 - data/lib/active_record/enum.rb +116 -76
 - data/lib/active_record/errors.rb +87 -48
 - data/lib/active_record/explain.rb +20 -9
 - data/lib/active_record/explain_registry.rb +1 -1
 - data/lib/active_record/explain_subscriber.rb +1 -1
 - data/lib/active_record/fixture_set/file.rb +26 -5
 - data/lib/active_record/fixtures.rb +77 -41
 - data/lib/active_record/gem_version.rb +4 -4
 - data/lib/active_record/inheritance.rb +32 -40
 - data/lib/active_record/integration.rb +17 -14
 - data/lib/active_record/internal_metadata.rb +56 -0
 - data/lib/active_record/legacy_yaml_adapter.rb +18 -2
 - data/lib/active_record/locale/en.yml +3 -2
 - data/lib/active_record/locking/optimistic.rb +15 -15
 - data/lib/active_record/locking/pessimistic.rb +1 -1
 - data/lib/active_record/log_subscriber.rb +48 -24
 - data/lib/active_record/migration.rb +362 -111
 - data/lib/active_record/migration/command_recorder.rb +59 -18
 - data/lib/active_record/migration/compatibility.rb +126 -0
 - data/lib/active_record/model_schema.rb +270 -73
 - data/lib/active_record/nested_attributes.rb +58 -29
 - data/lib/active_record/no_touching.rb +4 -0
 - data/lib/active_record/null_relation.rb +16 -8
 - data/lib/active_record/persistence.rb +152 -90
 - data/lib/active_record/query_cache.rb +18 -23
 - data/lib/active_record/querying.rb +12 -11
 - data/lib/active_record/railtie.rb +23 -16
 - data/lib/active_record/railties/controller_runtime.rb +1 -1
 - data/lib/active_record/railties/databases.rake +52 -41
 - data/lib/active_record/readonly_attributes.rb +1 -1
 - data/lib/active_record/reflection.rb +302 -115
 - data/lib/active_record/relation.rb +187 -120
 - data/lib/active_record/relation/batches.rb +141 -36
 - data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
 - data/lib/active_record/relation/calculations.rb +92 -117
 - data/lib/active_record/relation/delegation.rb +8 -20
 - data/lib/active_record/relation/finder_methods.rb +173 -89
 - data/lib/active_record/relation/from_clause.rb +32 -0
 - data/lib/active_record/relation/merger.rb +16 -42
 - data/lib/active_record/relation/predicate_builder.rb +120 -107
 - data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
 - data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
 - data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
 - data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
 - data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
 - data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
 - data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
 - data/lib/active_record/relation/query_attribute.rb +19 -0
 - data/lib/active_record/relation/query_methods.rb +308 -244
 - data/lib/active_record/relation/record_fetch_warning.rb +49 -0
 - data/lib/active_record/relation/spawn_methods.rb +4 -7
 - data/lib/active_record/relation/where_clause.rb +174 -0
 - data/lib/active_record/relation/where_clause_factory.rb +38 -0
 - data/lib/active_record/result.rb +11 -4
 - data/lib/active_record/runtime_registry.rb +1 -1
 - data/lib/active_record/sanitization.rb +105 -66
 - data/lib/active_record/schema.rb +26 -22
 - data/lib/active_record/schema_dumper.rb +54 -37
 - data/lib/active_record/schema_migration.rb +11 -14
 - data/lib/active_record/scoping.rb +34 -16
 - data/lib/active_record/scoping/default.rb +28 -10
 - data/lib/active_record/scoping/named.rb +59 -26
 - data/lib/active_record/secure_token.rb +38 -0
 - data/lib/active_record/serialization.rb +3 -5
 - data/lib/active_record/statement_cache.rb +17 -15
 - data/lib/active_record/store.rb +8 -3
 - data/lib/active_record/suppressor.rb +58 -0
 - data/lib/active_record/table_metadata.rb +69 -0
 - data/lib/active_record/tasks/database_tasks.rb +66 -49
 - data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +12 -3
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
 - data/lib/active_record/timestamp.rb +20 -9
 - data/lib/active_record/touch_later.rb +63 -0
 - data/lib/active_record/transactions.rb +139 -57
 - data/lib/active_record/type.rb +66 -17
 - data/lib/active_record/type/adapter_specific_registry.rb +130 -0
 - data/lib/active_record/type/date.rb +2 -45
 - data/lib/active_record/type/date_time.rb +2 -49
 - data/lib/active_record/type/internal/abstract_json.rb +33 -0
 - data/lib/active_record/type/internal/timezone.rb +15 -0
 - data/lib/active_record/type/serialized.rb +15 -14
 - data/lib/active_record/type/time.rb +10 -16
 - data/lib/active_record/type/type_map.rb +4 -4
 - data/lib/active_record/type_caster.rb +7 -0
 - data/lib/active_record/type_caster/connection.rb +29 -0
 - data/lib/active_record/type_caster/map.rb +19 -0
 - data/lib/active_record/validations.rb +33 -32
 - data/lib/active_record/validations/absence.rb +23 -0
 - data/lib/active_record/validations/associated.rb +10 -3
 - data/lib/active_record/validations/length.rb +24 -0
 - data/lib/active_record/validations/presence.rb +11 -12
 - data/lib/active_record/validations/uniqueness.rb +33 -33
 - data/lib/rails/generators/active_record/migration.rb +15 -0
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -5
 - data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
 - data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
 - data/lib/rails/generators/active_record/model/model_generator.rb +33 -16
 - data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
 - data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
 - metadata +58 -34
 - data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
 - data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
 - data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
 - data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
 - data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
 - data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
 - data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
 - data/lib/active_record/serializers/xml_serializer.rb +0 -193
 - data/lib/active_record/type/big_integer.rb +0 -13
 - data/lib/active_record/type/binary.rb +0 -50
 - data/lib/active_record/type/boolean.rb +0 -31
 - data/lib/active_record/type/decimal.rb +0 -64
 - data/lib/active_record/type/decimal_without_scale.rb +0 -11
 - data/lib/active_record/type/decorator.rb +0 -14
 - data/lib/active_record/type/float.rb +0 -19
 - data/lib/active_record/type/integer.rb +0 -59
 - data/lib/active_record/type/mutable.rb +0 -16
 - data/lib/active_record/type/numeric.rb +0 -36
 - data/lib/active_record/type/string.rb +0 -40
 - data/lib/active_record/type/text.rb +0 -11
 - data/lib/active_record/type/time_value.rb +0 -38
 - data/lib/active_record/type/unsigned_integer.rb +0 -15
 - data/lib/active_record/type/value.rb +0 -110
 
| 
         @@ -18,9 +18,9 @@ module ActiveRecord 
     | 
|
| 
       18 
18 
     | 
    
         
             
                  end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                  # Returns the maximum allowed length for an index name. This
         
     | 
| 
       21 
     | 
    
         
            -
                  # limit is enforced by  
     | 
| 
       22 
     | 
    
         
            -
                  #  
     | 
| 
       23 
     | 
    
         
            -
                  #  
     | 
| 
      
 21 
     | 
    
         
            +
                  # limit is enforced by \Rails and is less than or equal to
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # #index_name_length. The gap between
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # #index_name_length is to allow internal \Rails
         
     | 
| 
       24 
24 
     | 
    
         
             
                  # operations to use prefixes in temporary operations.
         
     | 
| 
       25 
25 
     | 
    
         
             
                  def allowed_index_name_length
         
     | 
| 
       26 
26 
     | 
    
         
             
                    index_name_length
         
     | 
| 
         @@ -27,9 +27,19 @@ module ActiveRecord 
     | 
|
| 
       27 
27 
     | 
    
         
             
                  end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
                  # Returns an ActiveRecord::Result instance.
         
     | 
| 
       30 
     | 
    
         
            -
                  def select_all(arel, name = nil, binds = [])
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def select_all(arel, name = nil, binds = [], preparable: nil)
         
     | 
| 
       31 
31 
     | 
    
         
             
                    arel, binds = binds_from_relation arel, binds
         
     | 
| 
       32 
     | 
    
         
            -
                     
     | 
| 
      
 32 
     | 
    
         
            +
                    sql = to_sql(arel, binds)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      preparable = false
         
     | 
| 
      
 35 
     | 
    
         
            +
                    else
         
     | 
| 
      
 36 
     | 
    
         
            +
                      preparable = visitor.preparable
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
                    if prepared_statements && preparable
         
     | 
| 
      
 39 
     | 
    
         
            +
                      select_prepared(sql, name, binds)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    else
         
     | 
| 
      
 41 
     | 
    
         
            +
                      select(sql, name, binds)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
       33 
43 
     | 
    
         
             
                  end
         
     | 
| 
       34 
44 
     | 
    
         | 
| 
       35 
45 
     | 
    
         
             
                  # Returns a record hash with the column names as keys and column values
         
     | 
| 
         @@ -40,33 +50,39 @@ module ActiveRecord 
     | 
|
| 
       40 
50 
     | 
    
         | 
| 
       41 
51 
     | 
    
         
             
                  # Returns a single value from a record
         
     | 
| 
       42 
52 
     | 
    
         
             
                  def select_value(arel, name = nil, binds = [])
         
     | 
| 
       43 
     | 
    
         
            -
                     
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 53 
     | 
    
         
            +
                    arel, binds = binds_from_relation arel, binds
         
     | 
| 
      
 54 
     | 
    
         
            +
                    if result = select_rows(to_sql(arel, binds), name, binds).first
         
     | 
| 
      
 55 
     | 
    
         
            +
                      result.first
         
     | 
| 
       45 
56 
     | 
    
         
             
                    end
         
     | 
| 
       46 
57 
     | 
    
         
             
                  end
         
     | 
| 
       47 
58 
     | 
    
         | 
| 
       48 
59 
     | 
    
         
             
                  # Returns an array of the values of the first column in a select:
         
     | 
| 
       49 
60 
     | 
    
         
             
                  #   select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
         
     | 
| 
       50 
     | 
    
         
            -
                  def select_values(arel, name = nil)
         
     | 
| 
       51 
     | 
    
         
            -
                    arel, binds = binds_from_relation arel,  
     | 
| 
      
 61 
     | 
    
         
            +
                  def select_values(arel, name = nil, binds = [])
         
     | 
| 
      
 62 
     | 
    
         
            +
                    arel, binds = binds_from_relation arel, binds
         
     | 
| 
       52 
63 
     | 
    
         
             
                    select_rows(to_sql(arel, binds), name, binds).map(&:first)
         
     | 
| 
       53 
64 
     | 
    
         
             
                  end
         
     | 
| 
       54 
65 
     | 
    
         | 
| 
       55 
66 
     | 
    
         
             
                  # Returns an array of arrays containing the field values.
         
     | 
| 
       56 
67 
     | 
    
         
             
                  # Order is the same as that returned by +columns+.
         
     | 
| 
       57 
68 
     | 
    
         
             
                  def select_rows(sql, name = nil, binds = [])
         
     | 
| 
      
 69 
     | 
    
         
            +
                    exec_query(sql, name, binds).rows
         
     | 
| 
       58 
70 
     | 
    
         
             
                  end
         
     | 
| 
       59 
     | 
    
         
            -
                  undef_method :select_rows
         
     | 
| 
       60 
71 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
                  # Executes the SQL statement in the context of this connection 
     | 
| 
      
 72 
     | 
    
         
            +
                  # Executes the SQL statement in the context of this connection and returns
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # the raw result from the connection adapter.
         
     | 
| 
      
 74 
     | 
    
         
            +
                  # Note: depending on your database connector, the result returned by this
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # method may be manually memory managed. Consider using the exec_query
         
     | 
| 
      
 76 
     | 
    
         
            +
                  # wrapper instead.
         
     | 
| 
       62 
77 
     | 
    
         
             
                  def execute(sql, name = nil)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    raise NotImplementedError
         
     | 
| 
       63 
79 
     | 
    
         
             
                  end
         
     | 
| 
       64 
     | 
    
         
            -
                  undef_method :execute
         
     | 
| 
       65 
80 
     | 
    
         | 
| 
       66 
81 
     | 
    
         
             
                  # Executes +sql+ statement in the context of this connection using
         
     | 
| 
       67 
82 
     | 
    
         
             
                  # +binds+ as the bind substitutes. +name+ is logged along with
         
     | 
| 
       68 
83 
     | 
    
         
             
                  # the executed +sql+ statement.
         
     | 
| 
       69 
     | 
    
         
            -
                  def exec_query(sql, name = 'SQL', binds = [])
         
     | 
| 
      
 84 
     | 
    
         
            +
                  def exec_query(sql, name = 'SQL', binds = [], prepare: false)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    raise NotImplementedError
         
     | 
| 
       70 
86 
     | 
    
         
             
                  end
         
     | 
| 
       71 
87 
     | 
    
         | 
| 
       72 
88 
     | 
    
         
             
                  # Executes insert +sql+ statement in the context of this connection using
         
     | 
| 
         @@ -95,7 +111,7 @@ module ActiveRecord 
     | 
|
| 
       95 
111 
     | 
    
         
             
                    exec_query(sql, name, binds)
         
     | 
| 
       96 
112 
     | 
    
         
             
                  end
         
     | 
| 
       97 
113 
     | 
    
         | 
| 
       98 
     | 
    
         
            -
                  #  
     | 
| 
      
 114 
     | 
    
         
            +
                  # Executes an INSERT query and returns the new record's ID
         
     | 
| 
       99 
115 
     | 
    
         
             
                  #
         
     | 
| 
       100 
116 
     | 
    
         
             
                  # +id_value+ will be returned unless the value is nil, in
         
     | 
| 
       101 
117 
     | 
    
         
             
                  # which case the database will attempt to calculate the last inserted
         
     | 
| 
         @@ -104,20 +120,27 @@ module ActiveRecord 
     | 
|
| 
       104 
120 
     | 
    
         
             
                  # If the next id was calculated in advance (as in Oracle), it should be
         
     | 
| 
       105 
121 
     | 
    
         
             
                  # passed in as +id_value+.
         
     | 
| 
       106 
122 
     | 
    
         
             
                  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
         
     | 
| 
       107 
     | 
    
         
            -
                    sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
         
     | 
| 
       108 
     | 
    
         
            -
                    value 
     | 
| 
      
 123 
     | 
    
         
            +
                    sql, binds, pk, sequence_name = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    value = exec_insert(sql, name, binds, pk, sequence_name)
         
     | 
| 
       109 
125 
     | 
    
         
             
                    id_value || last_inserted_id(value)
         
     | 
| 
       110 
126 
     | 
    
         
             
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  alias create insert
         
     | 
| 
      
 128 
     | 
    
         
            +
                  alias insert_sql insert
         
     | 
| 
      
 129 
     | 
    
         
            +
                  deprecate insert_sql: :insert
         
     | 
| 
       111 
130 
     | 
    
         | 
| 
       112 
131 
     | 
    
         
             
                  # Executes the update statement and returns the number of rows affected.
         
     | 
| 
       113 
132 
     | 
    
         
             
                  def update(arel, name = nil, binds = [])
         
     | 
| 
       114 
133 
     | 
    
         
             
                    exec_update(to_sql(arel, binds), name, binds)
         
     | 
| 
       115 
134 
     | 
    
         
             
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
                  alias update_sql update
         
     | 
| 
      
 136 
     | 
    
         
            +
                  deprecate update_sql: :update
         
     | 
| 
       116 
137 
     | 
    
         | 
| 
       117 
138 
     | 
    
         
             
                  # Executes the delete statement and returns the number of rows affected.
         
     | 
| 
       118 
139 
     | 
    
         
             
                  def delete(arel, name = nil, binds = [])
         
     | 
| 
       119 
140 
     | 
    
         
             
                    exec_delete(to_sql(arel, binds), name, binds)
         
     | 
| 
       120 
141 
     | 
    
         
             
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  alias delete_sql delete
         
     | 
| 
      
 143 
     | 
    
         
            +
                  deprecate delete_sql: :delete
         
     | 
| 
       121 
144 
     | 
    
         | 
| 
       122 
145 
     | 
    
         
             
                  # Returns +true+ when the connection adapter supports prepared statement
         
     | 
| 
       123 
146 
     | 
    
         
             
                  # caching, otherwise returns +false+
         
     | 
| 
         @@ -136,7 +159,7 @@ module ActiveRecord 
     | 
|
| 
       136 
159 
     | 
    
         
             
                  #
         
     | 
| 
       137 
160 
     | 
    
         
             
                  # In order to get around this problem, #transaction will emulate the effect
         
     | 
| 
       138 
161 
     | 
    
         
             
                  # of nested transactions, by using savepoints:
         
     | 
| 
       139 
     | 
    
         
            -
                  # http://dev.mysql.com/doc/refman/5. 
     | 
| 
      
 162 
     | 
    
         
            +
                  # http://dev.mysql.com/doc/refman/5.7/en/savepoint.html
         
     | 
| 
       140 
163 
     | 
    
         
             
                  # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
         
     | 
| 
       141 
164 
     | 
    
         
             
                  # supports savepoints.
         
     | 
| 
       142 
165 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -188,29 +211,25 @@ module ActiveRecord 
     | 
|
| 
       188 
211 
     | 
    
         
             
                  # You should consult the documentation for your database to understand the
         
     | 
| 
       189 
212 
     | 
    
         
             
                  # semantics of these different levels:
         
     | 
| 
       190 
213 
     | 
    
         
             
                  #
         
     | 
| 
       191 
     | 
    
         
            -
                  # * http://www.postgresql.org/docs/ 
     | 
| 
       192 
     | 
    
         
            -
                  # * https://dev.mysql.com/doc/refman/5. 
     | 
| 
      
 214 
     | 
    
         
            +
                  # * http://www.postgresql.org/docs/current/static/transaction-iso.html
         
     | 
| 
      
 215 
     | 
    
         
            +
                  # * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
         
     | 
| 
       193 
216 
     | 
    
         
             
                  #
         
     | 
| 
       194 
     | 
    
         
            -
                  # An  
     | 
| 
      
 217 
     | 
    
         
            +
                  # An ActiveRecord::TransactionIsolationError will be raised if:
         
     | 
| 
       195 
218 
     | 
    
         
             
                  #
         
     | 
| 
       196 
219 
     | 
    
         
             
                  # * The adapter does not support setting the isolation level
         
     | 
| 
       197 
220 
     | 
    
         
             
                  # * You are joining an existing open transaction
         
     | 
| 
       198 
221 
     | 
    
         
             
                  # * You are creating a nested (savepoint) transaction
         
     | 
| 
       199 
222 
     | 
    
         
             
                  #
         
     | 
| 
       200 
     | 
    
         
            -
                  # The  
     | 
| 
       201 
     | 
    
         
            -
                  # isolation level. 
     | 
| 
       202 
     | 
    
         
            -
                   
     | 
| 
       203 
     | 
    
         
            -
             
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
     | 
    
         
            -
                    options.assert_valid_keys :requires_new, :joinable, :isolation
         
     | 
| 
       206 
     | 
    
         
            -
             
     | 
| 
       207 
     | 
    
         
            -
                    if !options[:requires_new] && current_transaction.joinable?
         
     | 
| 
       208 
     | 
    
         
            -
                      if options[:isolation]
         
     | 
| 
      
 223 
     | 
    
         
            +
                  # The mysql2 and postgresql adapters support setting the transaction
         
     | 
| 
      
 224 
     | 
    
         
            +
                  # isolation level.
         
     | 
| 
      
 225 
     | 
    
         
            +
                  def transaction(requires_new: nil, isolation: nil, joinable: true)
         
     | 
| 
      
 226 
     | 
    
         
            +
                    if !requires_new && current_transaction.joinable?
         
     | 
| 
      
 227 
     | 
    
         
            +
                      if isolation
         
     | 
| 
       209 
228 
     | 
    
         
             
                        raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
         
     | 
| 
       210 
229 
     | 
    
         
             
                      end
         
     | 
| 
       211 
230 
     | 
    
         
             
                      yield
         
     | 
| 
       212 
231 
     | 
    
         
             
                    else
         
     | 
| 
       213 
     | 
    
         
            -
                      transaction_manager.within_new_transaction( 
     | 
| 
      
 232 
     | 
    
         
            +
                      transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) { yield }
         
     | 
| 
       214 
233 
     | 
    
         
             
                    end
         
     | 
| 
       215 
234 
     | 
    
         
             
                  rescue ActiveRecord::Rollback
         
     | 
| 
       216 
235 
     | 
    
         
             
                    # rollbacks are silently swallowed
         
     | 
| 
         @@ -225,7 +244,7 @@ module ActiveRecord 
     | 
|
| 
       225 
244 
     | 
    
         
             
                  end
         
     | 
| 
       226 
245 
     | 
    
         | 
| 
       227 
246 
     | 
    
         
             
                  def reset_transaction #:nodoc:
         
     | 
| 
       228 
     | 
    
         
            -
                    @transaction_manager = TransactionManager.new(self)
         
     | 
| 
      
 247 
     | 
    
         
            +
                    @transaction_manager = ConnectionAdapters::TransactionManager.new(self)
         
     | 
| 
       229 
248 
     | 
    
         
             
                  end
         
     | 
| 
       230 
249 
     | 
    
         | 
| 
       231 
250 
     | 
    
         
             
                  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
         
     | 
| 
         @@ -272,9 +291,6 @@ module ActiveRecord 
     | 
|
| 
       272 
291 
     | 
    
         
             
                    exec_rollback_to_savepoint(name)
         
     | 
| 
       273 
292 
     | 
    
         
             
                  end
         
     | 
| 
       274 
293 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
                  def exec_rollback_to_savepoint(name = nil) #:nodoc:
         
     | 
| 
       276 
     | 
    
         
            -
                  end
         
     | 
| 
       277 
     | 
    
         
            -
             
     | 
| 
       278 
294 
     | 
    
         
             
                  def default_sequence_name(table, column)
         
     | 
| 
       279 
295 
     | 
    
         
             
                    nil
         
     | 
| 
       280 
296 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -288,17 +304,24 @@ module ActiveRecord 
     | 
|
| 
       288 
304 
     | 
    
         
             
                  # something beyond a simple insert (eg. Oracle).
         
     | 
| 
       289 
305 
     | 
    
         
             
                  def insert_fixture(fixture, table_name)
         
     | 
| 
       290 
306 
     | 
    
         
             
                    fixture = fixture.stringify_keys
         
     | 
| 
       291 
     | 
    
         
            -
                    columns = schema_cache.columns_hash(table_name)
         
     | 
| 
       292 
307 
     | 
    
         | 
| 
       293 
     | 
    
         
            -
                     
     | 
| 
       294 
     | 
    
         
            -
                     
     | 
| 
      
 308 
     | 
    
         
            +
                    columns = schema_cache.columns_hash(table_name)
         
     | 
| 
      
 309 
     | 
    
         
            +
                    binds = fixture.map do |name, value|
         
     | 
| 
       295 
310 
     | 
    
         
             
                      if column = columns[name]
         
     | 
| 
       296 
     | 
    
         
            -
                         
     | 
| 
       297 
     | 
    
         
            -
                         
     | 
| 
      
 311 
     | 
    
         
            +
                        type = lookup_cast_type_from_column(column)
         
     | 
| 
      
 312 
     | 
    
         
            +
                        Relation::QueryAttribute.new(name, value, type)
         
     | 
| 
       298 
313 
     | 
    
         
             
                      else
         
     | 
| 
       299 
314 
     | 
    
         
             
                        raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
         
     | 
| 
       300 
315 
     | 
    
         
             
                      end
         
     | 
| 
       301 
316 
     | 
    
         
             
                    end
         
     | 
| 
      
 317 
     | 
    
         
            +
                    key_list = fixture.keys.map { |name| quote_column_name(name) }
         
     | 
| 
      
 318 
     | 
    
         
            +
                    value_list = prepare_binds_for_database(binds).map do |value|
         
     | 
| 
      
 319 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 320 
     | 
    
         
            +
                        quote(value)
         
     | 
| 
      
 321 
     | 
    
         
            +
                      rescue TypeError
         
     | 
| 
      
 322 
     | 
    
         
            +
                        quote(YAML.dump(value))
         
     | 
| 
      
 323 
     | 
    
         
            +
                      end
         
     | 
| 
      
 324 
     | 
    
         
            +
                    end
         
     | 
| 
       302 
325 
     | 
    
         | 
| 
       303 
326 
     | 
    
         
             
                    execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
         
     | 
| 
       304 
327 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -329,18 +352,12 @@ module ActiveRecord 
     | 
|
| 
       329 
352 
     | 
    
         
             
                  # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
         
     | 
| 
       330 
353 
     | 
    
         
             
                  # on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
         
     | 
| 
       331 
354 
     | 
    
         
             
                  # an UPDATE statement, so in the MySQL adapters we redefine this to do that.
         
     | 
| 
       332 
     | 
    
         
            -
                  def join_to_update(update, select)  
     | 
| 
       333 
     | 
    
         
            -
                    key = update.key
         
     | 
| 
      
 355 
     | 
    
         
            +
                  def join_to_update(update, select, key) # :nodoc:
         
     | 
| 
       334 
356 
     | 
    
         
             
                    subselect = subquery_for(key, select)
         
     | 
| 
       335 
357 
     | 
    
         | 
| 
       336 
358 
     | 
    
         
             
                    update.where key.in(subselect)
         
     | 
| 
       337 
359 
     | 
    
         
             
                  end
         
     | 
| 
       338 
     | 
    
         
            -
             
     | 
| 
       339 
     | 
    
         
            -
                  def join_to_delete(delete, select, key) #:nodoc:
         
     | 
| 
       340 
     | 
    
         
            -
                    subselect = subquery_for(key, select)
         
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
       342 
     | 
    
         
            -
                    delete.where key.in(subselect)
         
     | 
| 
       343 
     | 
    
         
            -
                  end
         
     | 
| 
      
 360 
     | 
    
         
            +
                  alias join_to_delete join_to_update
         
     | 
| 
       344 
361 
     | 
    
         | 
| 
       345 
362 
     | 
    
         
             
                  protected
         
     | 
| 
       346 
363 
     | 
    
         | 
| 
         @@ -353,28 +370,15 @@ module ActiveRecord 
     | 
|
| 
       353 
370 
     | 
    
         | 
| 
       354 
371 
     | 
    
         
             
                    # Returns an ActiveRecord::Result instance.
         
     | 
| 
       355 
372 
     | 
    
         
             
                    def select(sql, name = nil, binds = [])
         
     | 
| 
       356 
     | 
    
         
            -
                      exec_query(sql, name, binds)
         
     | 
| 
       357 
     | 
    
         
            -
                    end
         
     | 
| 
       358 
     | 
    
         
            -
             
     | 
| 
       359 
     | 
    
         
            -
             
     | 
| 
       360 
     | 
    
         
            -
                    # Returns the last auto-generated ID from the affected table.
         
     | 
| 
       361 
     | 
    
         
            -
                    def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
         
     | 
| 
       362 
     | 
    
         
            -
                      execute(sql, name)
         
     | 
| 
       363 
     | 
    
         
            -
                      id_value
         
     | 
| 
       364 
     | 
    
         
            -
                    end
         
     | 
| 
       365 
     | 
    
         
            -
             
     | 
| 
       366 
     | 
    
         
            -
                    # Executes the update statement and returns the number of rows affected.
         
     | 
| 
       367 
     | 
    
         
            -
                    def update_sql(sql, name = nil)
         
     | 
| 
       368 
     | 
    
         
            -
                      execute(sql, name)
         
     | 
| 
      
 373 
     | 
    
         
            +
                      exec_query(sql, name, binds, prepare: false)
         
     | 
| 
       369 
374 
     | 
    
         
             
                    end
         
     | 
| 
       370 
375 
     | 
    
         | 
| 
       371 
     | 
    
         
            -
                     
     | 
| 
       372 
     | 
    
         
            -
             
     | 
| 
       373 
     | 
    
         
            -
                      update_sql(sql, name)
         
     | 
| 
      
 376 
     | 
    
         
            +
                    def select_prepared(sql, name = nil, binds = [])
         
     | 
| 
      
 377 
     | 
    
         
            +
                      exec_query(sql, name, binds, prepare: true)
         
     | 
| 
       374 
378 
     | 
    
         
             
                    end
         
     | 
| 
       375 
379 
     | 
    
         | 
| 
       376 
380 
     | 
    
         
             
                    def sql_for_insert(sql, pk, id_value, sequence_name, binds)
         
     | 
| 
       377 
     | 
    
         
            -
                      [sql, binds]
         
     | 
| 
      
 381 
     | 
    
         
            +
                      [sql, binds, pk, sequence_name]
         
     | 
| 
       378 
382 
     | 
    
         
             
                    end
         
     | 
| 
       379 
383 
     | 
    
         | 
| 
       380 
384 
     | 
    
         
             
                    def last_inserted_id(result)
         
     | 
| 
         @@ -384,7 +388,7 @@ module ActiveRecord 
     | 
|
| 
       384 
388 
     | 
    
         | 
| 
       385 
389 
     | 
    
         
             
                    def binds_from_relation(relation, binds)
         
     | 
| 
       386 
390 
     | 
    
         
             
                      if relation.is_a?(Relation) && binds.empty?
         
     | 
| 
       387 
     | 
    
         
            -
                        relation, binds = relation.arel, relation. 
     | 
| 
      
 391 
     | 
    
         
            +
                        relation, binds = relation.arel, relation.bound_attributes
         
     | 
| 
       388 
392 
     | 
    
         
             
                      end
         
     | 
| 
       389 
393 
     | 
    
         
             
                      [relation, binds]
         
     | 
| 
       390 
394 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -4,6 +4,9 @@ module ActiveRecord 
     | 
|
| 
       4 
4 
     | 
    
         
             
                  class << self
         
     | 
| 
       5 
5 
     | 
    
         
             
                    def included(base) #:nodoc:
         
     | 
| 
       6 
6 
     | 
    
         
             
                      dirties_query_cache base, :insert, :update, :delete, :rollback_to_savepoint, :rollback_db_transaction
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                      base.set_callback :checkout, :after, :configure_query_cache!
         
     | 
| 
      
 9 
     | 
    
         
            +
                      base.set_callback :checkin, :after, :disable_query_cache!
         
     | 
| 
       7 
10 
     | 
    
         
             
                    end
         
     | 
| 
       8 
11 
     | 
    
         | 
| 
       9 
12 
     | 
    
         
             
                    def dirties_query_cache(base, *method_names)
         
     | 
| 
         @@ -18,6 +21,27 @@ module ActiveRecord 
     | 
|
| 
       18 
21 
     | 
    
         
             
                    end
         
     | 
| 
       19 
22 
     | 
    
         
             
                  end
         
     | 
| 
       20 
23 
     | 
    
         | 
| 
      
 24 
     | 
    
         
            +
                  module ConnectionPoolConfiguration
         
     | 
| 
      
 25 
     | 
    
         
            +
                    def initialize(*)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      super
         
     | 
| 
      
 27 
     | 
    
         
            +
                      @query_cache_enabled = Concurrent::Map.new { false }
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    def enable_query_cache!
         
     | 
| 
      
 31 
     | 
    
         
            +
                      @query_cache_enabled[connection_cache_key(Thread.current)] = true
         
     | 
| 
      
 32 
     | 
    
         
            +
                      connection.enable_query_cache! if active_connection?
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    def disable_query_cache!
         
     | 
| 
      
 36 
     | 
    
         
            +
                      @query_cache_enabled.delete connection_cache_key(Thread.current)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      connection.disable_query_cache! if active_connection?
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    def query_cache_enabled
         
     | 
| 
      
 41 
     | 
    
         
            +
                      @query_cache_enabled[connection_cache_key(Thread.current)]
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
       21 
45 
     | 
    
         
             
                  attr_reader :query_cache, :query_cache_enabled
         
     | 
| 
       22 
46 
     | 
    
         | 
| 
       23 
47 
     | 
    
         
             
                  def initialize(*)
         
     | 
| 
         @@ -41,6 +65,7 @@ module ActiveRecord 
     | 
|
| 
       41 
65 
     | 
    
         | 
| 
       42 
66 
     | 
    
         
             
                  def disable_query_cache!
         
     | 
| 
       43 
67 
     | 
    
         
             
                    @query_cache_enabled = false
         
     | 
| 
      
 68 
     | 
    
         
            +
                    clear_query_cache
         
     | 
| 
       44 
69 
     | 
    
         
             
                  end
         
     | 
| 
       45 
70 
     | 
    
         | 
| 
       46 
71 
     | 
    
         
             
                  # Disable the query cache within the block.
         
     | 
| 
         @@ -61,11 +86,11 @@ module ActiveRecord 
     | 
|
| 
       61 
86 
     | 
    
         
             
                    @query_cache.clear
         
     | 
| 
       62 
87 
     | 
    
         
             
                  end
         
     | 
| 
       63 
88 
     | 
    
         | 
| 
       64 
     | 
    
         
            -
                  def select_all(arel, name = nil, binds = [])
         
     | 
| 
      
 89 
     | 
    
         
            +
                  def select_all(arel, name = nil, binds = [], preparable: nil)
         
     | 
| 
       65 
90 
     | 
    
         
             
                    if @query_cache_enabled && !locked?(arel)
         
     | 
| 
       66 
91 
     | 
    
         
             
                      arel, binds = binds_from_relation arel, binds
         
     | 
| 
       67 
92 
     | 
    
         
             
                      sql = to_sql(arel, binds)
         
     | 
| 
       68 
     | 
    
         
            -
                      cache_sql(sql, binds) { super(sql, name, binds) }
         
     | 
| 
      
 93 
     | 
    
         
            +
                      cache_sql(sql, binds) { super(sql, name, binds, preparable: preparable) }
         
     | 
| 
       69 
94 
     | 
    
         
             
                    else
         
     | 
| 
       70 
95 
     | 
    
         
             
                      super
         
     | 
| 
       71 
96 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -76,8 +101,14 @@ module ActiveRecord 
     | 
|
| 
       76 
101 
     | 
    
         
             
                  def cache_sql(sql, binds)
         
     | 
| 
       77 
102 
     | 
    
         
             
                    result =
         
     | 
| 
       78 
103 
     | 
    
         
             
                      if @query_cache[sql].key?(binds)
         
     | 
| 
       79 
     | 
    
         
            -
                        ActiveSupport::Notifications.instrument( 
     | 
| 
       80 
     | 
    
         
            -
                           
     | 
| 
      
 104 
     | 
    
         
            +
                        ActiveSupport::Notifications.instrument(
         
     | 
| 
      
 105 
     | 
    
         
            +
                          "sql.active_record",
         
     | 
| 
      
 106 
     | 
    
         
            +
                          sql: sql,
         
     | 
| 
      
 107 
     | 
    
         
            +
                          binds: binds,
         
     | 
| 
      
 108 
     | 
    
         
            +
                          type_casted_binds: -> { type_casted_binds(binds) },
         
     | 
| 
      
 109 
     | 
    
         
            +
                          name: "CACHE",
         
     | 
| 
      
 110 
     | 
    
         
            +
                          connection_id: object_id,
         
     | 
| 
      
 111 
     | 
    
         
            +
                        )
         
     | 
| 
       81 
112 
     | 
    
         
             
                        @query_cache[sql][binds]
         
     | 
| 
       82 
113 
     | 
    
         
             
                      else
         
     | 
| 
       83 
114 
     | 
    
         
             
                        @query_cache[sql][binds] = yield
         
     | 
| 
         @@ -90,6 +121,10 @@ module ActiveRecord 
     | 
|
| 
       90 
121 
     | 
    
         
             
                  def locked?(arel)
         
     | 
| 
       91 
122 
     | 
    
         
             
                    arel.respond_to?(:locked) && arel.locked
         
     | 
| 
       92 
123 
     | 
    
         
             
                  end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                  def configure_query_cache!
         
     | 
| 
      
 126 
     | 
    
         
            +
                    enable_query_cache! if pool.query_cache_enabled
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
       93 
128 
     | 
    
         
             
                end
         
     | 
| 
       94 
129 
     | 
    
         
             
              end
         
     | 
| 
       95 
130 
     | 
    
         
             
            end
         
     | 
| 
         @@ -11,7 +11,13 @@ module ActiveRecord 
     | 
|
| 
       11 
11 
     | 
    
         
             
                    return value.quoted_id if value.respond_to?(:quoted_id)
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                    if column
         
     | 
| 
       14 
     | 
    
         
            -
                       
     | 
| 
      
 14 
     | 
    
         
            +
                      ActiveSupport::Deprecation.warn(<<-MSG.squish)
         
     | 
| 
      
 15 
     | 
    
         
            +
                        Passing a column to `quote` has been deprecated. It is only used
         
     | 
| 
      
 16 
     | 
    
         
            +
                        for type casting, which should be handled elsewhere. See
         
     | 
| 
      
 17 
     | 
    
         
            +
                        https://github.com/rails/arel/commit/6160bfbda1d1781c3b08a33ec4955f170e95be11
         
     | 
| 
      
 18 
     | 
    
         
            +
                        for more information.
         
     | 
| 
      
 19 
     | 
    
         
            +
                      MSG
         
     | 
| 
      
 20 
     | 
    
         
            +
                      value = type_cast_from_column(column, value)
         
     | 
| 
       15 
21 
     | 
    
         
             
                    end
         
     | 
| 
       16 
22 
     | 
    
         | 
| 
       17 
23 
     | 
    
         
             
                    _quote(value)
         
     | 
| 
         @@ -20,13 +26,13 @@ module ActiveRecord 
     | 
|
| 
       20 
26 
     | 
    
         
             
                  # Cast a +value+ to a type that the database understands. For example,
         
     | 
| 
       21 
27 
     | 
    
         
             
                  # SQLite does not understand dates, so this method will convert a Date
         
     | 
| 
       22 
28 
     | 
    
         
             
                  # to a String.
         
     | 
| 
       23 
     | 
    
         
            -
                  def type_cast(value, column)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def type_cast(value, column = nil)
         
     | 
| 
       24 
30 
     | 
    
         
             
                    if value.respond_to?(:quoted_id) && value.respond_to?(:id)
         
     | 
| 
       25 
31 
     | 
    
         
             
                      return value.id
         
     | 
| 
       26 
32 
     | 
    
         
             
                    end
         
     | 
| 
       27 
33 
     | 
    
         | 
| 
       28 
34 
     | 
    
         
             
                    if column
         
     | 
| 
       29 
     | 
    
         
            -
                      value = column 
     | 
| 
      
 35 
     | 
    
         
            +
                      value = type_cast_from_column(column, value)
         
     | 
| 
       30 
36 
     | 
    
         
             
                    end
         
     | 
| 
       31 
37 
     | 
    
         | 
| 
       32 
38 
     | 
    
         
             
                    _type_cast(value)
         
     | 
| 
         @@ -35,15 +41,49 @@ module ActiveRecord 
     | 
|
| 
       35 
41 
     | 
    
         
             
                    raise TypeError, "can't cast #{value.class}#{to_type}"
         
     | 
| 
       36 
42 
     | 
    
         
             
                  end
         
     | 
| 
       37 
43 
     | 
    
         | 
| 
      
 44 
     | 
    
         
            +
                  # If you are having to call this function, you are likely doing something
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # wrong. The column does not have sufficient type information if the user
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # provided a custom type on the class level either explicitly (via
         
     | 
| 
      
 47 
     | 
    
         
            +
                  # Attributes::ClassMethods#attribute) or implicitly (via
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # AttributeMethods::Serialization::ClassMethods#serialize, +time_zone_aware_attributes+).
         
     | 
| 
      
 49 
     | 
    
         
            +
                  # In almost all cases, the sql type should only be used to change quoting behavior, when the primitive to
         
     | 
| 
      
 50 
     | 
    
         
            +
                  # represent the type doesn't sufficiently reflect the differences
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # (varchar vs binary) for example. The type used to get this primitive
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # should have been provided before reaching the connection adapter.
         
     | 
| 
      
 53 
     | 
    
         
            +
                  def type_cast_from_column(column, value) # :nodoc:
         
     | 
| 
      
 54 
     | 
    
         
            +
                    if column
         
     | 
| 
      
 55 
     | 
    
         
            +
                      type = lookup_cast_type_from_column(column)
         
     | 
| 
      
 56 
     | 
    
         
            +
                      type.serialize(value)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    else
         
     | 
| 
      
 58 
     | 
    
         
            +
                      value
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  # See docs for #type_cast_from_column
         
     | 
| 
      
 63 
     | 
    
         
            +
                  def lookup_cast_type_from_column(column) # :nodoc:
         
     | 
| 
      
 64 
     | 
    
         
            +
                    lookup_cast_type(column.sql_type)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  def fetch_type_metadata(sql_type)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    cast_type = lookup_cast_type(sql_type)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    SqlTypeMetadata.new(
         
     | 
| 
      
 70 
     | 
    
         
            +
                      sql_type: sql_type,
         
     | 
| 
      
 71 
     | 
    
         
            +
                      type: cast_type.type,
         
     | 
| 
      
 72 
     | 
    
         
            +
                      limit: cast_type.limit,
         
     | 
| 
      
 73 
     | 
    
         
            +
                      precision: cast_type.precision,
         
     | 
| 
      
 74 
     | 
    
         
            +
                      scale: cast_type.scale,
         
     | 
| 
      
 75 
     | 
    
         
            +
                    )
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
       38 
78 
     | 
    
         
             
                  # Quotes a string, escaping any ' (single quote) and \ (backslash)
         
     | 
| 
       39 
79 
     | 
    
         
             
                  # characters.
         
     | 
| 
       40 
80 
     | 
    
         
             
                  def quote_string(s)
         
     | 
| 
       41 
     | 
    
         
            -
                    s.gsub( 
     | 
| 
      
 81 
     | 
    
         
            +
                    s.gsub('\\'.freeze, '\&\&'.freeze).gsub("'".freeze, "''".freeze) # ' (for ruby-mode)
         
     | 
| 
       42 
82 
     | 
    
         
             
                  end
         
     | 
| 
       43 
83 
     | 
    
         | 
| 
       44 
84 
     | 
    
         
             
                  # Quotes the column name. Defaults to no quoting.
         
     | 
| 
       45 
85 
     | 
    
         
             
                  def quote_column_name(column_name)
         
     | 
| 
       46 
     | 
    
         
            -
                    column_name
         
     | 
| 
      
 86 
     | 
    
         
            +
                    column_name.to_s
         
     | 
| 
       47 
87 
     | 
    
         
             
                  end
         
     | 
| 
       48 
88 
     | 
    
         | 
| 
       49 
89 
     | 
    
         
             
                  # Quotes the table name. Defaults to column name quoting.
         
     | 
| 
         @@ -54,7 +94,7 @@ module ActiveRecord 
     | 
|
| 
       54 
94 
     | 
    
         
             
                  # Override to return the quoted table name for assignment. Defaults to
         
     | 
| 
       55 
95 
     | 
    
         
             
                  # table quoting.
         
     | 
| 
       56 
96 
     | 
    
         
             
                  #
         
     | 
| 
       57 
     | 
    
         
            -
                  # This works for  
     | 
| 
      
 97 
     | 
    
         
            +
                  # This works for mysql2 where table.column can be used to
         
     | 
| 
       58 
98 
     | 
    
         
             
                  # resolve ambiguity.
         
     | 
| 
       59 
99 
     | 
    
         
             
                  #
         
     | 
| 
       60 
100 
     | 
    
         
             
                  # We override this in the sqlite3 and postgresql adapters to use only
         
     | 
| 
         @@ -63,22 +103,33 @@ module ActiveRecord 
     | 
|
| 
       63 
103 
     | 
    
         
             
                    quote_table_name("#{table}.#{attr}")
         
     | 
| 
       64 
104 
     | 
    
         
             
                  end
         
     | 
| 
       65 
105 
     | 
    
         | 
| 
      
 106 
     | 
    
         
            +
                  def quote_default_expression(value, column) # :nodoc:
         
     | 
| 
      
 107 
     | 
    
         
            +
                    if value.is_a?(Proc)
         
     | 
| 
      
 108 
     | 
    
         
            +
                      value.call
         
     | 
| 
      
 109 
     | 
    
         
            +
                    else
         
     | 
| 
      
 110 
     | 
    
         
            +
                      value = lookup_cast_type(column.sql_type).serialize(value)
         
     | 
| 
      
 111 
     | 
    
         
            +
                      quote(value)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
       66 
115 
     | 
    
         
             
                  def quoted_true
         
     | 
| 
       67 
     | 
    
         
            -
                    "'t'"
         
     | 
| 
      
 116 
     | 
    
         
            +
                    "'t'".freeze
         
     | 
| 
       68 
117 
     | 
    
         
             
                  end
         
     | 
| 
       69 
118 
     | 
    
         | 
| 
       70 
119 
     | 
    
         
             
                  def unquoted_true
         
     | 
| 
       71 
     | 
    
         
            -
                    't'
         
     | 
| 
      
 120 
     | 
    
         
            +
                    't'.freeze
         
     | 
| 
       72 
121 
     | 
    
         
             
                  end
         
     | 
| 
       73 
122 
     | 
    
         | 
| 
       74 
123 
     | 
    
         
             
                  def quoted_false
         
     | 
| 
       75 
     | 
    
         
            -
                    "'f'"
         
     | 
| 
      
 124 
     | 
    
         
            +
                    "'f'".freeze
         
     | 
| 
       76 
125 
     | 
    
         
             
                  end
         
     | 
| 
       77 
126 
     | 
    
         | 
| 
       78 
127 
     | 
    
         
             
                  def unquoted_false
         
     | 
| 
       79 
     | 
    
         
            -
                    'f'
         
     | 
| 
      
 128 
     | 
    
         
            +
                    'f'.freeze
         
     | 
| 
       80 
129 
     | 
    
         
             
                  end
         
     | 
| 
       81 
130 
     | 
    
         | 
| 
      
 131 
     | 
    
         
            +
                  # Quote date/time values for use in SQL input. Includes microseconds
         
     | 
| 
      
 132 
     | 
    
         
            +
                  # if the value is a Time responding to usec.
         
     | 
| 
       82 
133 
     | 
    
         
             
                  def quoted_date(value)
         
     | 
| 
       83 
134 
     | 
    
         
             
                    if value.acts_like?(:time)
         
     | 
| 
       84 
135 
     | 
    
         
             
                      zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
         
     | 
| 
         @@ -88,7 +139,28 @@ module ActiveRecord 
     | 
|
| 
       88 
139 
     | 
    
         
             
                      end
         
     | 
| 
       89 
140 
     | 
    
         
             
                    end
         
     | 
| 
       90 
141 
     | 
    
         | 
| 
       91 
     | 
    
         
            -
                    value.to_s(:db)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    result = value.to_s(:db)
         
     | 
| 
      
 143 
     | 
    
         
            +
                    if value.respond_to?(:usec) && value.usec > 0
         
     | 
| 
      
 144 
     | 
    
         
            +
                      "#{result}.#{sprintf("%06d", value.usec)}"
         
     | 
| 
      
 145 
     | 
    
         
            +
                    else
         
     | 
| 
      
 146 
     | 
    
         
            +
                      result
         
     | 
| 
      
 147 
     | 
    
         
            +
                    end
         
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  def quoted_time(value) # :nodoc:
         
     | 
| 
      
 151 
     | 
    
         
            +
                    quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, '')
         
     | 
| 
      
 152 
     | 
    
         
            +
                  end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                  def prepare_binds_for_database(binds) # :nodoc:
         
     | 
| 
      
 155 
     | 
    
         
            +
                    binds.map(&:value_for_database)
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                  def type_casted_binds(binds) # :nodoc:
         
     | 
| 
      
 159 
     | 
    
         
            +
                    if binds.first.is_a?(Array)
         
     | 
| 
      
 160 
     | 
    
         
            +
                      binds.map { |column, value| type_cast(value, column) }
         
     | 
| 
      
 161 
     | 
    
         
            +
                    else
         
     | 
| 
      
 162 
     | 
    
         
            +
                      binds.map { |attr| type_cast(attr.value_for_database) }
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
       92 
164 
     | 
    
         
             
                  end
         
     | 
| 
       93 
165 
     | 
    
         | 
| 
       94 
166 
     | 
    
         
             
                  private
         
     | 
| 
         @@ -107,11 +179,11 @@ module ActiveRecord 
     | 
|
| 
       107 
179 
     | 
    
         
             
                    # BigDecimals need to be put in a non-normalized form and quoted.
         
     | 
| 
       108 
180 
     | 
    
         
             
                    when BigDecimal then value.to_s('F')
         
     | 
| 
       109 
181 
     | 
    
         
             
                    when Numeric, ActiveSupport::Duration then value.to_s
         
     | 
| 
      
 182 
     | 
    
         
            +
                    when Type::Time::Value then "'#{quoted_time(value)}'"
         
     | 
| 
       110 
183 
     | 
    
         
             
                    when Date, Time then "'#{quoted_date(value)}'"
         
     | 
| 
       111 
184 
     | 
    
         
             
                    when Symbol     then "'#{quote_string(value.to_s)}'"
         
     | 
| 
       112 
185 
     | 
    
         
             
                    when Class      then "'#{value}'"
         
     | 
| 
       113 
     | 
    
         
            -
                    else
         
     | 
| 
       114 
     | 
    
         
            -
                      "'#{quote_string(YAML.dump(value))}'"
         
     | 
| 
      
 186 
     | 
    
         
            +
                    else raise TypeError, "can't quote #{value.class.name}"
         
     | 
| 
       115 
187 
     | 
    
         
             
                    end
         
     | 
| 
       116 
188 
     | 
    
         
             
                  end
         
     | 
| 
       117 
189 
     | 
    
         | 
| 
         @@ -123,6 +195,7 @@ module ActiveRecord 
     | 
|
| 
       123 
195 
     | 
    
         
             
                    when false      then unquoted_false
         
     | 
| 
       124 
196 
     | 
    
         
             
                    # BigDecimals need to be put in a non-normalized form and quoted.
         
     | 
| 
       125 
197 
     | 
    
         
             
                    when BigDecimal then value.to_s('F')
         
     | 
| 
      
 198 
     | 
    
         
            +
                    when Type::Time::Value then quoted_time(value)
         
     | 
| 
       126 
199 
     | 
    
         
             
                    when Date, Time then quoted_date(value)
         
     | 
| 
       127 
200 
     | 
    
         
             
                    when *types_which_need_no_typecasting
         
     | 
| 
       128 
201 
     | 
    
         
             
                      value
         
     |