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
 
| 
         @@ -10,33 +10,46 @@ module ActiveRecord 
     | 
|
| 
       10 
10 
     | 
    
         
             
                    @columns      = {}
         
     | 
| 
       11 
11 
     | 
    
         
             
                    @columns_hash = {}
         
     | 
| 
       12 
12 
     | 
    
         
             
                    @primary_keys = {}
         
     | 
| 
       13 
     | 
    
         
            -
                    @ 
     | 
| 
      
 13 
     | 
    
         
            +
                    @data_sources = {}
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize_dup(other)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    super
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @columns      = @columns.dup
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @columns_hash = @columns_hash.dup
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @primary_keys = @primary_keys.dup
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @data_sources = @data_sources.dup
         
     | 
| 
       14 
22 
     | 
    
         
             
                  end
         
     | 
| 
       15 
23 
     | 
    
         | 
| 
       16 
24 
     | 
    
         
             
                  def primary_keys(table_name)
         
     | 
| 
       17 
     | 
    
         
            -
                    @primary_keys[table_name] ||=  
     | 
| 
      
 25 
     | 
    
         
            +
                    @primary_keys[table_name] ||= data_source_exists?(table_name) ? connection.primary_key(table_name) : nil
         
     | 
| 
       18 
26 
     | 
    
         
             
                  end
         
     | 
| 
       19 
27 
     | 
    
         | 
| 
       20 
28 
     | 
    
         
             
                  # A cached lookup for table existence.
         
     | 
| 
       21 
     | 
    
         
            -
                  def  
     | 
| 
       22 
     | 
    
         
            -
                     
     | 
| 
       23 
     | 
    
         
            -
                    return @ 
     | 
| 
      
 29 
     | 
    
         
            +
                  def data_source_exists?(name)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    prepare_data_sources if @data_sources.empty?
         
     | 
| 
      
 31 
     | 
    
         
            +
                    return @data_sources[name] if @data_sources.key? name
         
     | 
| 
       24 
32 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                    @ 
     | 
| 
      
 33 
     | 
    
         
            +
                    @data_sources[name] = connection.data_source_exists?(name)
         
     | 
| 
       26 
34 
     | 
    
         
             
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  alias table_exists? data_source_exists?
         
     | 
| 
      
 36 
     | 
    
         
            +
                  deprecate :table_exists? => "use #data_source_exists? instead"
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       27 
38 
     | 
    
         | 
| 
       28 
39 
     | 
    
         
             
                  # Add internal cache for table with +table_name+.
         
     | 
| 
       29 
40 
     | 
    
         
             
                  def add(table_name)
         
     | 
| 
       30 
     | 
    
         
            -
                    if  
     | 
| 
      
 41 
     | 
    
         
            +
                    if data_source_exists?(table_name)
         
     | 
| 
       31 
42 
     | 
    
         
             
                      primary_keys(table_name)
         
     | 
| 
       32 
43 
     | 
    
         
             
                      columns(table_name)
         
     | 
| 
       33 
44 
     | 
    
         
             
                      columns_hash(table_name)
         
     | 
| 
       34 
45 
     | 
    
         
             
                    end
         
     | 
| 
       35 
46 
     | 
    
         
             
                  end
         
     | 
| 
       36 
47 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
                  def  
     | 
| 
       38 
     | 
    
         
            -
                    @ 
     | 
| 
      
 48 
     | 
    
         
            +
                  def data_sources(name)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @data_sources[name]
         
     | 
| 
       39 
50 
     | 
    
         
             
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  alias tables data_sources
         
     | 
| 
      
 52 
     | 
    
         
            +
                  deprecate :tables => "use #data_sources instead"
         
     | 
| 
       40 
53 
     | 
    
         | 
| 
       41 
54 
     | 
    
         
             
                  # Get the columns for a table
         
     | 
| 
       42 
55 
     | 
    
         
             
                  def columns(table_name)
         
     | 
| 
         @@ -56,38 +69,38 @@ module ActiveRecord 
     | 
|
| 
       56 
69 
     | 
    
         
             
                    @columns.clear
         
     | 
| 
       57 
70 
     | 
    
         
             
                    @columns_hash.clear
         
     | 
| 
       58 
71 
     | 
    
         
             
                    @primary_keys.clear
         
     | 
| 
       59 
     | 
    
         
            -
                    @ 
     | 
| 
      
 72 
     | 
    
         
            +
                    @data_sources.clear
         
     | 
| 
       60 
73 
     | 
    
         
             
                    @version = nil
         
     | 
| 
       61 
74 
     | 
    
         
             
                  end
         
     | 
| 
       62 
75 
     | 
    
         | 
| 
       63 
76 
     | 
    
         
             
                  def size
         
     | 
| 
       64 
     | 
    
         
            -
                    [@columns, @columns_hash, @primary_keys, @ 
     | 
| 
       65 
     | 
    
         
            -
                      x.size
         
     | 
| 
       66 
     | 
    
         
            -
                    }.inject :+
         
     | 
| 
      
 77 
     | 
    
         
            +
                    [@columns, @columns_hash, @primary_keys, @data_sources].map(&:size).inject :+
         
     | 
| 
       67 
78 
     | 
    
         
             
                  end
         
     | 
| 
       68 
79 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
                  # Clear out internal caches for  
     | 
| 
       70 
     | 
    
         
            -
                  def  
     | 
| 
       71 
     | 
    
         
            -
                    @columns.delete  
     | 
| 
       72 
     | 
    
         
            -
                    @columns_hash.delete  
     | 
| 
       73 
     | 
    
         
            -
                    @primary_keys.delete  
     | 
| 
       74 
     | 
    
         
            -
                    @ 
     | 
| 
      
 80 
     | 
    
         
            +
                  # Clear out internal caches for the data source +name+.
         
     | 
| 
      
 81 
     | 
    
         
            +
                  def clear_data_source_cache!(name)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    @columns.delete name
         
     | 
| 
      
 83 
     | 
    
         
            +
                    @columns_hash.delete name
         
     | 
| 
      
 84 
     | 
    
         
            +
                    @primary_keys.delete name
         
     | 
| 
      
 85 
     | 
    
         
            +
                    @data_sources.delete name
         
     | 
| 
       75 
86 
     | 
    
         
             
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
                  alias clear_table_cache! clear_data_source_cache!
         
     | 
| 
      
 88 
     | 
    
         
            +
                  deprecate :clear_table_cache! => "use #clear_data_source_cache! instead"
         
     | 
| 
       76 
89 
     | 
    
         | 
| 
       77 
90 
     | 
    
         
             
                  def marshal_dump
         
     | 
| 
       78 
91 
     | 
    
         
             
                    # if we get current version during initialization, it happens stack over flow.
         
     | 
| 
       79 
92 
     | 
    
         
             
                    @version = ActiveRecord::Migrator.current_version
         
     | 
| 
       80 
     | 
    
         
            -
                    [@version, @columns, @columns_hash, @primary_keys, @ 
     | 
| 
      
 93 
     | 
    
         
            +
                    [@version, @columns, @columns_hash, @primary_keys, @data_sources]
         
     | 
| 
       81 
94 
     | 
    
         
             
                  end
         
     | 
| 
       82 
95 
     | 
    
         | 
| 
       83 
96 
     | 
    
         
             
                  def marshal_load(array)
         
     | 
| 
       84 
     | 
    
         
            -
                    @version, @columns, @columns_hash, @primary_keys, @ 
     | 
| 
      
 97 
     | 
    
         
            +
                    @version, @columns, @columns_hash, @primary_keys, @data_sources = array
         
     | 
| 
       85 
98 
     | 
    
         
             
                  end
         
     | 
| 
       86 
99 
     | 
    
         | 
| 
       87 
100 
     | 
    
         
             
                  private
         
     | 
| 
       88 
101 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
                    def  
     | 
| 
       90 
     | 
    
         
            -
                      connection. 
     | 
| 
      
 102 
     | 
    
         
            +
                    def prepare_data_sources
         
     | 
| 
      
 103 
     | 
    
         
            +
                      connection.data_sources.each { |source| @data_sources[source] = true }
         
     | 
| 
       91 
104 
     | 
    
         
             
                    end
         
     | 
| 
       92 
105 
     | 
    
         
             
                end
         
     | 
| 
       93 
106 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              # :stopdoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
              module ConnectionAdapters
         
     | 
| 
      
 4 
     | 
    
         
            +
                class SqlTypeMetadata
         
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :sql_type, :type, :limit, :precision, :scale
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(sql_type: nil, type: nil, limit: nil, precision: nil, scale: nil)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @sql_type = sql_type
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @type = type
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @limit = limit
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @precision = precision
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @scale = scale
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def ==(other)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    other.is_a?(SqlTypeMetadata) &&
         
     | 
| 
      
 17 
     | 
    
         
            +
                      attributes_for_hash == other.attributes_for_hash
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  alias eql? ==
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def hash
         
     | 
| 
      
 22 
     | 
    
         
            +
                    attributes_for_hash.hash
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def attributes_for_hash
         
     | 
| 
      
 28 
     | 
    
         
            +
                    [self.class, sql_type, type, limit, precision, scale]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ConnectionAdapters
         
     | 
| 
      
 3 
     | 
    
         
            +
                module SQLite3
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class ExplainPrettyPrinter # :nodoc:
         
     | 
| 
      
 5 
     | 
    
         
            +
                    # Pretty prints the result of an EXPLAIN QUERY PLAN in a way that resembles
         
     | 
| 
      
 6 
     | 
    
         
            +
                    # the output of the SQLite shell:
         
     | 
| 
      
 7 
     | 
    
         
            +
                    #
         
     | 
| 
      
 8 
     | 
    
         
            +
                    #   0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    #   0|1|1|SCAN TABLE posts (~100000 rows)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    #
         
     | 
| 
      
 11 
     | 
    
         
            +
                    def pp(result)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      result.rows.map do |row|
         
     | 
| 
      
 13 
     | 
    
         
            +
                        row.join('|')
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end.join("\n") + "\n"
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ConnectionAdapters
         
     | 
| 
      
 3 
     | 
    
         
            +
                module SQLite3
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module Quoting # :nodoc:
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def quote_string(s)
         
     | 
| 
      
 6 
     | 
    
         
            +
                      @connection.class.quote(s)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def quote_table_name_for_assignment(table, attr)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      quote_column_name(attr)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    def quote_column_name(name)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      @quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def quoted_time(value)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    private
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    def _quote(value)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      if value.is_a?(Type::Binary::Data)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        "x'#{value.hex}'"
         
     | 
| 
      
 26 
     | 
    
         
            +
                      else
         
     | 
| 
      
 27 
     | 
    
         
            +
                        super
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    def _type_cast(value)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      case value
         
     | 
| 
      
 33 
     | 
    
         
            +
                      when BigDecimal
         
     | 
| 
      
 34 
     | 
    
         
            +
                        value.to_f
         
     | 
| 
      
 35 
     | 
    
         
            +
                      when String
         
     | 
| 
      
 36 
     | 
    
         
            +
                        if value.encoding == Encoding::ASCII_8BIT
         
     | 
| 
      
 37 
     | 
    
         
            +
                          super(value.encode(Encoding::UTF_8))
         
     | 
| 
      
 38 
     | 
    
         
            +
                        else
         
     | 
| 
      
 39 
     | 
    
         
            +
                          super
         
     | 
| 
      
 40 
     | 
    
         
            +
                        end
         
     | 
| 
      
 41 
     | 
    
         
            +
                      else
         
     | 
| 
      
 42 
     | 
    
         
            +
                        super
         
     | 
| 
      
 43 
     | 
    
         
            +
                      end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ConnectionAdapters
         
     | 
| 
      
 3 
     | 
    
         
            +
                module SQLite3
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class SchemaCreation < AbstractAdapter::SchemaCreation
         
     | 
| 
      
 5 
     | 
    
         
            +
                    private
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                      def column_options(o)
         
     | 
| 
      
 8 
     | 
    
         
            +
                        options = super
         
     | 
| 
      
 9 
     | 
    
         
            +
                        options[:null] = false if o.primary_key
         
     | 
| 
      
 10 
     | 
    
         
            +
                        options
         
     | 
| 
      
 11 
     | 
    
         
            +
                      end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                      def add_column_options!(sql, options)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        if options[:collation]
         
     | 
| 
      
 15 
     | 
    
         
            +
                          sql << " COLLATE \"#{options[:collation]}\""
         
     | 
| 
      
 16 
     | 
    
         
            +
                        end
         
     | 
| 
      
 17 
     | 
    
         
            +
                        super
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,13 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'active_record/connection_adapters/abstract_adapter'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'active_record/connection_adapters/statement_pool'
         
     | 
| 
       3 
     | 
    
         
            -
            require ' 
     | 
| 
      
 3 
     | 
    
         
            +
            require 'active_record/connection_adapters/sqlite3/explain_pretty_printer'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'active_record/connection_adapters/sqlite3/quoting'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'active_record/connection_adapters/sqlite3/schema_creation'
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
            gem 'sqlite3', '~> 1.3.6'
         
     | 
| 
       6 
8 
     | 
    
         
             
            require 'sqlite3'
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
       8 
10 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       9 
11 
     | 
    
         
             
              module ConnectionHandling # :nodoc:
         
     | 
| 
       10 
     | 
    
         
            -
                # sqlite3 adapter reuses sqlite_connection.
         
     | 
| 
       11 
12 
     | 
    
         
             
                def sqlite3_connection(config)
         
     | 
| 
       12 
13 
     | 
    
         
             
                  # Require database.
         
     | 
| 
       13 
14 
     | 
    
         
             
                  unless config[:database]
         
     | 
| 
         @@ -33,7 +34,7 @@ module ActiveRecord 
     | 
|
| 
       33 
34 
     | 
    
         
             
                  ConnectionAdapters::SQLite3Adapter.new(db, logger, nil, config)
         
     | 
| 
       34 
35 
     | 
    
         
             
                rescue Errno::ENOENT => error
         
     | 
| 
       35 
36 
     | 
    
         
             
                  if error.message.include?("No such file or directory")
         
     | 
| 
       36 
     | 
    
         
            -
                    raise ActiveRecord::NoDatabaseError 
     | 
| 
      
 37 
     | 
    
         
            +
                    raise ActiveRecord::NoDatabaseError
         
     | 
| 
       37 
38 
     | 
    
         
             
                  else
         
     | 
| 
       38 
39 
     | 
    
         
             
                    raise
         
     | 
| 
       39 
40 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -41,15 +42,6 @@ module ActiveRecord 
     | 
|
| 
       41 
42 
     | 
    
         
             
              end
         
     | 
| 
       42 
43 
     | 
    
         | 
| 
       43 
44 
     | 
    
         
             
              module ConnectionAdapters #:nodoc:
         
     | 
| 
       44 
     | 
    
         
            -
                class SQLite3Binary < Type::Binary # :nodoc:
         
     | 
| 
       45 
     | 
    
         
            -
                  def cast_value(value)
         
     | 
| 
       46 
     | 
    
         
            -
                    if value.encoding != Encoding::ASCII_8BIT
         
     | 
| 
       47 
     | 
    
         
            -
                      value = value.force_encoding(Encoding::ASCII_8BIT)
         
     | 
| 
       48 
     | 
    
         
            -
                    end
         
     | 
| 
       49 
     | 
    
         
            -
                    value
         
     | 
| 
       50 
     | 
    
         
            -
                  end
         
     | 
| 
       51 
     | 
    
         
            -
                end
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
45 
     | 
    
         
             
                # The SQLite3 adapter works SQLite 3.6.16 or newer
         
     | 
| 
       54 
46 
     | 
    
         
             
                # with the sqlite3-ruby drivers (available as gem from https://rubygems.org/gems/sqlite3).
         
     | 
| 
       55 
47 
     | 
    
         
             
                #
         
     | 
| 
         @@ -58,7 +50,8 @@ module ActiveRecord 
     | 
|
| 
       58 
50 
     | 
    
         
             
                # * <tt>:database</tt> - Path to the database file.
         
     | 
| 
       59 
51 
     | 
    
         
             
                class SQLite3Adapter < AbstractAdapter
         
     | 
| 
       60 
52 
     | 
    
         
             
                  ADAPTER_NAME = 'SQLite'.freeze
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  include SQLite3::Quoting
         
     | 
| 
       62 
55 
     | 
    
         | 
| 
       63 
56 
     | 
    
         
             
                  NATIVE_DATABASE_TYPES = {
         
     | 
| 
       64 
57 
     | 
    
         
             
                    primary_key:  'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL',
         
     | 
| 
         @@ -75,55 +68,26 @@ module ActiveRecord 
     | 
|
| 
       75 
68 
     | 
    
         
             
                  }
         
     | 
| 
       76 
69 
     | 
    
         | 
| 
       77 
70 
     | 
    
         
             
                  class StatementPool < ConnectionAdapters::StatementPool
         
     | 
| 
       78 
     | 
    
         
            -
                    def initialize(connection, max)
         
     | 
| 
       79 
     | 
    
         
            -
                      super
         
     | 
| 
       80 
     | 
    
         
            -
                      @cache = Hash.new { |h,pid| h[pid] = {} }
         
     | 
| 
       81 
     | 
    
         
            -
                    end
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                    def each(&block); cache.each(&block); end
         
     | 
| 
       84 
     | 
    
         
            -
                    def key?(key);    cache.key?(key); end
         
     | 
| 
       85 
     | 
    
         
            -
                    def [](key);      cache[key]; end
         
     | 
| 
       86 
     | 
    
         
            -
                    def length;       cache.length; end
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
                    def []=(sql, key)
         
     | 
| 
       89 
     | 
    
         
            -
                      while @max <= cache.size
         
     | 
| 
       90 
     | 
    
         
            -
                        dealloc(cache.shift.last[:stmt])
         
     | 
| 
       91 
     | 
    
         
            -
                      end
         
     | 
| 
       92 
     | 
    
         
            -
                      cache[sql] = key
         
     | 
| 
       93 
     | 
    
         
            -
                    end
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
                    def clear
         
     | 
| 
       96 
     | 
    
         
            -
                      cache.each_value do |hash|
         
     | 
| 
       97 
     | 
    
         
            -
                        dealloc hash[:stmt]
         
     | 
| 
       98 
     | 
    
         
            -
                      end
         
     | 
| 
       99 
     | 
    
         
            -
                      cache.clear
         
     | 
| 
       100 
     | 
    
         
            -
                    end
         
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
71 
     | 
    
         
             
                    private
         
     | 
| 
       103 
     | 
    
         
            -
                    def cache
         
     | 
| 
       104 
     | 
    
         
            -
                      @cache[$$]
         
     | 
| 
       105 
     | 
    
         
            -
                    end
         
     | 
| 
       106 
72 
     | 
    
         | 
| 
       107 
73 
     | 
    
         
             
                    def dealloc(stmt)
         
     | 
| 
       108 
     | 
    
         
            -
                      stmt.close unless stmt.closed?
         
     | 
| 
      
 74 
     | 
    
         
            +
                      stmt[:stmt].close unless stmt[:stmt].closed?
         
     | 
| 
       109 
75 
     | 
    
         
             
                    end
         
     | 
| 
       110 
76 
     | 
    
         
             
                  end
         
     | 
| 
       111 
77 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                  def  
     | 
| 
       113 
     | 
    
         
            -
                     
     | 
| 
      
 78 
     | 
    
         
            +
                  def schema_creation # :nodoc:
         
     | 
| 
      
 79 
     | 
    
         
            +
                    SQLite3::SchemaCreation.new self
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
       114 
81 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                     
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                    @config = config
         
     | 
| 
      
 82 
     | 
    
         
            +
                  def arel_visitor # :nodoc:
         
     | 
| 
      
 83 
     | 
    
         
            +
                    Arel::Visitors::SQLite.new(self)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
       119 
85 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
      
 86 
     | 
    
         
            +
                  def initialize(connection, logger, connection_options, config)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    super(connection, logger, config)
         
     | 
| 
       121 
88 
     | 
    
         | 
| 
       122 
     | 
    
         
            -
                     
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                    else
         
     | 
| 
       125 
     | 
    
         
            -
                      @prepared_statements = false
         
     | 
| 
       126 
     | 
    
         
            -
                    end
         
     | 
| 
      
 89 
     | 
    
         
            +
                    @active     = nil
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
         
     | 
| 
       127 
91 
     | 
    
         
             
                  end
         
     | 
| 
       128 
92 
     | 
    
         | 
| 
       129 
93 
     | 
    
         
             
                  def supports_ddl_transactions?
         
     | 
| 
         @@ -161,6 +125,14 @@ module ActiveRecord 
     | 
|
| 
       161 
125 
     | 
    
         
             
                    true
         
     | 
| 
       162 
126 
     | 
    
         
             
                  end
         
     | 
| 
       163 
127 
     | 
    
         | 
| 
      
 128 
     | 
    
         
            +
                  def supports_datetime_with_precision?
         
     | 
| 
      
 129 
     | 
    
         
            +
                    true
         
     | 
| 
      
 130 
     | 
    
         
            +
                  end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                  def supports_multi_insert?
         
     | 
| 
      
 133 
     | 
    
         
            +
                    sqlite_version >= '3.7.11'
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
       164 
136 
     | 
    
         
             
                  def active?
         
     | 
| 
       165 
137 
     | 
    
         
             
                    @active != false
         
     | 
| 
       166 
138 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -182,6 +154,10 @@ module ActiveRecord 
     | 
|
| 
       182 
154 
     | 
    
         
             
                    true
         
     | 
| 
       183 
155 
     | 
    
         
             
                  end
         
     | 
| 
       184 
156 
     | 
    
         | 
| 
      
 157 
     | 
    
         
            +
                  def valid_type?(type)
         
     | 
| 
      
 158 
     | 
    
         
            +
                    true
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
       185 
161 
     | 
    
         
             
                  # Returns 62. SQLite supports index names up to 64
         
     | 
| 
       186 
162 
     | 
    
         
             
                  # characters. The rest is used by rails internally to perform
         
     | 
| 
       187 
163 
     | 
    
         
             
                  # temporary rename operations
         
     | 
| 
         @@ -202,93 +178,31 @@ module ActiveRecord 
     | 
|
| 
       202 
178 
     | 
    
         
             
                    true
         
     | 
| 
       203 
179 
     | 
    
         
             
                  end
         
     | 
| 
       204 
180 
     | 
    
         | 
| 
       205 
     | 
    
         
            -
                  # QUOTING ==================================================
         
     | 
| 
       206 
     | 
    
         
            -
             
     | 
| 
       207 
     | 
    
         
            -
                  def _quote(value) # :nodoc:
         
     | 
| 
       208 
     | 
    
         
            -
                    case value
         
     | 
| 
       209 
     | 
    
         
            -
                    when Type::Binary::Data
         
     | 
| 
       210 
     | 
    
         
            -
                      "x'#{value.hex}'"
         
     | 
| 
       211 
     | 
    
         
            -
                    else
         
     | 
| 
       212 
     | 
    
         
            -
                      super
         
     | 
| 
       213 
     | 
    
         
            -
                    end
         
     | 
| 
       214 
     | 
    
         
            -
                  end
         
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
                  def _type_cast(value) # :nodoc:
         
     | 
| 
       217 
     | 
    
         
            -
                    case value
         
     | 
| 
       218 
     | 
    
         
            -
                    when BigDecimal
         
     | 
| 
       219 
     | 
    
         
            -
                      value.to_f
         
     | 
| 
       220 
     | 
    
         
            -
                    when String
         
     | 
| 
       221 
     | 
    
         
            -
                      if value.encoding == Encoding::ASCII_8BIT
         
     | 
| 
       222 
     | 
    
         
            -
                        super(value.encode(Encoding::UTF_8))
         
     | 
| 
       223 
     | 
    
         
            -
                      else
         
     | 
| 
       224 
     | 
    
         
            -
                        super
         
     | 
| 
       225 
     | 
    
         
            -
                      end
         
     | 
| 
       226 
     | 
    
         
            -
                    else
         
     | 
| 
       227 
     | 
    
         
            -
                      super
         
     | 
| 
       228 
     | 
    
         
            -
                    end
         
     | 
| 
       229 
     | 
    
         
            -
                  end
         
     | 
| 
       230 
     | 
    
         
            -
             
     | 
| 
       231 
     | 
    
         
            -
                  def quote_string(s) #:nodoc:
         
     | 
| 
       232 
     | 
    
         
            -
                    @connection.class.quote(s)
         
     | 
| 
       233 
     | 
    
         
            -
                  end
         
     | 
| 
       234 
     | 
    
         
            -
             
     | 
| 
       235 
     | 
    
         
            -
                  def quote_table_name_for_assignment(table, attr)
         
     | 
| 
       236 
     | 
    
         
            -
                    quote_column_name(attr)
         
     | 
| 
       237 
     | 
    
         
            -
                  end
         
     | 
| 
       238 
     | 
    
         
            -
             
     | 
| 
       239 
     | 
    
         
            -
                  def quote_column_name(name) #:nodoc:
         
     | 
| 
       240 
     | 
    
         
            -
                    %Q("#{name.to_s.gsub('"', '""')}")
         
     | 
| 
       241 
     | 
    
         
            -
                  end
         
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
                  # Quote date/time values for use in SQL input. Includes microseconds
         
     | 
| 
       244 
     | 
    
         
            -
                  # if the value is a Time responding to usec.
         
     | 
| 
       245 
     | 
    
         
            -
                  def quoted_date(value) #:nodoc:
         
     | 
| 
       246 
     | 
    
         
            -
                    if value.respond_to?(:usec)
         
     | 
| 
       247 
     | 
    
         
            -
                      "#{super}.#{sprintf("%06d", value.usec)}"
         
     | 
| 
       248 
     | 
    
         
            -
                    else
         
     | 
| 
       249 
     | 
    
         
            -
                      super
         
     | 
| 
       250 
     | 
    
         
            -
                    end
         
     | 
| 
       251 
     | 
    
         
            -
                  end
         
     | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
       253 
181 
     | 
    
         
             
                  #--
         
     | 
| 
       254 
182 
     | 
    
         
             
                  # DATABASE STATEMENTS ======================================
         
     | 
| 
       255 
183 
     | 
    
         
             
                  #++
         
     | 
| 
       256 
184 
     | 
    
         | 
| 
       257 
185 
     | 
    
         
             
                  def explain(arel, binds = [])
         
     | 
| 
       258 
186 
     | 
    
         
             
                    sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
         
     | 
| 
       259 
     | 
    
         
            -
                    ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', []))
         
     | 
| 
       260 
     | 
    
         
            -
                  end
         
     | 
| 
       261 
     | 
    
         
            -
             
     | 
| 
       262 
     | 
    
         
            -
                  class ExplainPrettyPrinter
         
     | 
| 
       263 
     | 
    
         
            -
                    # Pretty prints the result of a EXPLAIN QUERY PLAN in a way that resembles
         
     | 
| 
       264 
     | 
    
         
            -
                    # the output of the SQLite shell:
         
     | 
| 
       265 
     | 
    
         
            -
                    #
         
     | 
| 
       266 
     | 
    
         
            -
                    #   0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
         
     | 
| 
       267 
     | 
    
         
            -
                    #   0|1|1|SCAN TABLE posts (~100000 rows)
         
     | 
| 
       268 
     | 
    
         
            -
                    #
         
     | 
| 
       269 
     | 
    
         
            -
                    def pp(result) # :nodoc:
         
     | 
| 
       270 
     | 
    
         
            -
                      result.rows.map do |row|
         
     | 
| 
       271 
     | 
    
         
            -
                        row.join('|')
         
     | 
| 
       272 
     | 
    
         
            -
                      end.join("\n") + "\n"
         
     | 
| 
       273 
     | 
    
         
            -
                    end
         
     | 
| 
      
 187 
     | 
    
         
            +
                    SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', []))
         
     | 
| 
       274 
188 
     | 
    
         
             
                  end
         
     | 
| 
       275 
189 
     | 
    
         | 
| 
       276 
     | 
    
         
            -
                  def exec_query(sql, name = nil, binds = [])
         
     | 
| 
       277 
     | 
    
         
            -
                    type_casted_binds = binds 
     | 
| 
       278 
     | 
    
         
            -
                      [col, type_cast(val, col)]
         
     | 
| 
       279 
     | 
    
         
            -
                    }
         
     | 
| 
      
 190 
     | 
    
         
            +
                  def exec_query(sql, name = nil, binds = [], prepare: false)
         
     | 
| 
      
 191 
     | 
    
         
            +
                    type_casted_binds = type_casted_binds(binds)
         
     | 
| 
       280 
192 
     | 
    
         | 
| 
       281 
     | 
    
         
            -
                    log(sql, name, type_casted_binds) do
         
     | 
| 
      
 193 
     | 
    
         
            +
                    log(sql, name, binds, type_casted_binds) do
         
     | 
| 
       282 
194 
     | 
    
         
             
                      # Don't cache statements if they are not prepared
         
     | 
| 
       283 
     | 
    
         
            -
                       
     | 
| 
      
 195 
     | 
    
         
            +
                      unless prepare
         
     | 
| 
       284 
196 
     | 
    
         
             
                        stmt    = @connection.prepare(sql)
         
     | 
| 
       285 
197 
     | 
    
         
             
                        begin
         
     | 
| 
       286 
198 
     | 
    
         
             
                          cols    = stmt.columns
         
     | 
| 
      
 199 
     | 
    
         
            +
                          unless without_prepared_statement?(binds)
         
     | 
| 
      
 200 
     | 
    
         
            +
                            stmt.bind_params(type_casted_binds)
         
     | 
| 
      
 201 
     | 
    
         
            +
                          end
         
     | 
| 
       287 
202 
     | 
    
         
             
                          records = stmt.to_a
         
     | 
| 
       288 
203 
     | 
    
         
             
                        ensure
         
     | 
| 
       289 
204 
     | 
    
         
             
                          stmt.close
         
     | 
| 
       290 
205 
     | 
    
         
             
                        end
         
     | 
| 
       291 
     | 
    
         
            -
                        stmt = records
         
     | 
| 
       292 
206 
     | 
    
         
             
                      else
         
     | 
| 
       293 
207 
     | 
    
         
             
                        cache = @statements[sql] ||= {
         
     | 
| 
       294 
208 
     | 
    
         
             
                          :stmt => @connection.prepare(sql)
         
     | 
| 
         @@ -296,10 +210,11 @@ module ActiveRecord 
     | 
|
| 
       296 
210 
     | 
    
         
             
                        stmt = cache[:stmt]
         
     | 
| 
       297 
211 
     | 
    
         
             
                        cols = cache[:cols] ||= stmt.columns
         
     | 
| 
       298 
212 
     | 
    
         
             
                        stmt.reset!
         
     | 
| 
       299 
     | 
    
         
            -
                        stmt.bind_params 
     | 
| 
      
 213 
     | 
    
         
            +
                        stmt.bind_params(type_casted_binds)
         
     | 
| 
      
 214 
     | 
    
         
            +
                        records = stmt.to_a
         
     | 
| 
       300 
215 
     | 
    
         
             
                      end
         
     | 
| 
       301 
216 
     | 
    
         | 
| 
       302 
     | 
    
         
            -
                      ActiveRecord::Result.new(cols,  
     | 
| 
      
 217 
     | 
    
         
            +
                      ActiveRecord::Result.new(cols, records)
         
     | 
| 
       303 
218 
     | 
    
         
             
                    end
         
     | 
| 
       304 
219 
     | 
    
         
             
                  end
         
     | 
| 
       305 
220 
     | 
    
         | 
| 
         @@ -317,26 +232,6 @@ module ActiveRecord 
     | 
|
| 
       317 
232 
     | 
    
         
             
                    log(sql, name) { @connection.execute(sql) }
         
     | 
| 
       318 
233 
     | 
    
         
             
                  end
         
     | 
| 
       319 
234 
     | 
    
         | 
| 
       320 
     | 
    
         
            -
                  def update_sql(sql, name = nil) #:nodoc:
         
     | 
| 
       321 
     | 
    
         
            -
                    super
         
     | 
| 
       322 
     | 
    
         
            -
                    @connection.changes
         
     | 
| 
       323 
     | 
    
         
            -
                  end
         
     | 
| 
       324 
     | 
    
         
            -
             
     | 
| 
       325 
     | 
    
         
            -
                  def delete_sql(sql, name = nil) #:nodoc:
         
     | 
| 
       326 
     | 
    
         
            -
                    sql += " WHERE 1=1" unless sql =~ /WHERE/i
         
     | 
| 
       327 
     | 
    
         
            -
                    super sql, name
         
     | 
| 
       328 
     | 
    
         
            -
                  end
         
     | 
| 
       329 
     | 
    
         
            -
             
     | 
| 
       330 
     | 
    
         
            -
                  def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
         
     | 
| 
       331 
     | 
    
         
            -
                    super
         
     | 
| 
       332 
     | 
    
         
            -
                    id_value || @connection.last_insert_row_id
         
     | 
| 
       333 
     | 
    
         
            -
                  end
         
     | 
| 
       334 
     | 
    
         
            -
                  alias :create :insert_sql
         
     | 
| 
       335 
     | 
    
         
            -
             
     | 
| 
       336 
     | 
    
         
            -
                  def select_rows(sql, name = nil, binds = [])
         
     | 
| 
       337 
     | 
    
         
            -
                    exec_query(sql, name, binds).rows
         
     | 
| 
       338 
     | 
    
         
            -
                  end
         
     | 
| 
       339 
     | 
    
         
            -
             
     | 
| 
       340 
235 
     | 
    
         
             
                  def begin_db_transaction #:nodoc:
         
     | 
| 
       341 
236 
     | 
    
         
             
                    log('begin transaction',nil) { @connection.transaction }
         
     | 
| 
       342 
237 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -351,27 +246,61 @@ module ActiveRecord 
     | 
|
| 
       351 
246 
     | 
    
         | 
| 
       352 
247 
     | 
    
         
             
                  # SCHEMA STATEMENTS ========================================
         
     | 
| 
       353 
248 
     | 
    
         | 
| 
       354 
     | 
    
         
            -
                  def tables(name = nil 
     | 
| 
       355 
     | 
    
         
            -
                     
     | 
| 
       356 
     | 
    
         
            -
                       
     | 
| 
       357 
     | 
    
         
            -
                       
     | 
| 
       358 
     | 
    
         
            -
                       
     | 
| 
       359 
     | 
    
         
            -
                     
     | 
| 
       360 
     | 
    
         
            -
             
     | 
| 
       361 
     | 
    
         
            -
             
     | 
| 
       362 
     | 
    
         
            -
             
     | 
| 
       363 
     | 
    
         
            -
             
     | 
| 
      
 249 
     | 
    
         
            +
                  def tables(name = nil) # :nodoc:
         
     | 
| 
      
 250 
     | 
    
         
            +
                    ActiveSupport::Deprecation.warn(<<-MSG.squish)
         
     | 
| 
      
 251 
     | 
    
         
            +
                      #tables currently returns both tables and views.
         
     | 
| 
      
 252 
     | 
    
         
            +
                      This behavior is deprecated and will be changed with Rails 5.1 to only return tables.
         
     | 
| 
      
 253 
     | 
    
         
            +
                      Use #data_sources instead.
         
     | 
| 
      
 254 
     | 
    
         
            +
                    MSG
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
                    if name
         
     | 
| 
      
 257 
     | 
    
         
            +
                      ActiveSupport::Deprecation.warn(<<-MSG.squish)
         
     | 
| 
      
 258 
     | 
    
         
            +
                        Passing arguments to #tables is deprecated without replacement.
         
     | 
| 
      
 259 
     | 
    
         
            +
                      MSG
         
     | 
| 
       364 
260 
     | 
    
         
             
                    end
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                    data_sources
         
     | 
| 
      
 263 
     | 
    
         
            +
                  end
         
     | 
| 
      
 264 
     | 
    
         
            +
             
     | 
| 
      
 265 
     | 
    
         
            +
                  def data_sources
         
     | 
| 
      
 266 
     | 
    
         
            +
                    select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", 'SCHEMA')
         
     | 
| 
       365 
267 
     | 
    
         
             
                  end
         
     | 
| 
       366 
     | 
    
         
            -
                  alias data_sources tables
         
     | 
| 
       367 
268 
     | 
    
         | 
| 
       368 
269 
     | 
    
         
             
                  def table_exists?(table_name)
         
     | 
| 
       369 
     | 
    
         
            -
                     
     | 
| 
      
 270 
     | 
    
         
            +
                    ActiveSupport::Deprecation.warn(<<-MSG.squish)
         
     | 
| 
      
 271 
     | 
    
         
            +
                      #table_exists? currently checks both tables and views.
         
     | 
| 
      
 272 
     | 
    
         
            +
                      This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
         
     | 
| 
      
 273 
     | 
    
         
            +
                      Use #data_source_exists? instead.
         
     | 
| 
      
 274 
     | 
    
         
            +
                    MSG
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                    data_source_exists?(table_name)
         
     | 
| 
      
 277 
     | 
    
         
            +
                  end
         
     | 
| 
      
 278 
     | 
    
         
            +
             
     | 
| 
      
 279 
     | 
    
         
            +
                  def data_source_exists?(table_name)
         
     | 
| 
      
 280 
     | 
    
         
            +
                    return false unless table_name.present?
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
                    sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
         
     | 
| 
      
 283 
     | 
    
         
            +
                    sql << " AND name = #{quote(table_name)}"
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
                    select_values(sql, 'SCHEMA').any?
         
     | 
| 
      
 286 
     | 
    
         
            +
                  end
         
     | 
| 
      
 287 
     | 
    
         
            +
             
     | 
| 
      
 288 
     | 
    
         
            +
                  def views # :nodoc:
         
     | 
| 
      
 289 
     | 
    
         
            +
                    select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", 'SCHEMA')
         
     | 
| 
      
 290 
     | 
    
         
            +
                  end
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
      
 292 
     | 
    
         
            +
                  def view_exists?(view_name) # :nodoc:
         
     | 
| 
      
 293 
     | 
    
         
            +
                    return false unless view_name.present?
         
     | 
| 
      
 294 
     | 
    
         
            +
             
     | 
| 
      
 295 
     | 
    
         
            +
                    sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
         
     | 
| 
      
 296 
     | 
    
         
            +
                    sql << " AND name = #{quote(view_name)}"
         
     | 
| 
      
 297 
     | 
    
         
            +
             
     | 
| 
      
 298 
     | 
    
         
            +
                    select_values(sql, 'SCHEMA').any?
         
     | 
| 
       370 
299 
     | 
    
         
             
                  end
         
     | 
| 
       371 
     | 
    
         
            -
                  alias data_source_exists? table_exists?
         
     | 
| 
       372 
300 
     | 
    
         | 
| 
       373 
301 
     | 
    
         
             
                  # Returns an array of +Column+ objects for the table specified by +table_name+.
         
     | 
| 
       374 
     | 
    
         
            -
                  def columns(table_name)  
     | 
| 
      
 302 
     | 
    
         
            +
                  def columns(table_name) # :nodoc:
         
     | 
| 
      
 303 
     | 
    
         
            +
                    table_name = table_name.to_s
         
     | 
| 
       375 
304 
     | 
    
         
             
                    table_structure(table_name).map do |field|
         
     | 
| 
       376 
305 
     | 
    
         
             
                      case field["dflt_value"]
         
     | 
| 
       377 
306 
     | 
    
         
             
                      when /^null$/i
         
     | 
| 
         @@ -382,9 +311,10 @@ module ActiveRecord 
     | 
|
| 
       382 
311 
     | 
    
         
             
                        field["dflt_value"] = $1.gsub('""', '"')
         
     | 
| 
       383 
312 
     | 
    
         
             
                      end
         
     | 
| 
       384 
313 
     | 
    
         | 
| 
      
 314 
     | 
    
         
            +
                      collation = field['collation']
         
     | 
| 
       385 
315 
     | 
    
         
             
                      sql_type = field['type']
         
     | 
| 
       386 
     | 
    
         
            -
                       
     | 
| 
       387 
     | 
    
         
            -
                      new_column(field['name'], field['dflt_value'],  
     | 
| 
      
 316 
     | 
    
         
            +
                      type_metadata = fetch_type_metadata(sql_type)
         
     | 
| 
      
 317 
     | 
    
         
            +
                      new_column(field['name'], field['dflt_value'], type_metadata, field['notnull'].to_i == 0, table_name, nil, collation)
         
     | 
| 
       388 
318 
     | 
    
         
             
                    end
         
     | 
| 
       389 
319 
     | 
    
         
             
                  end
         
     | 
| 
       390 
320 
     | 
    
         | 
| 
         @@ -413,13 +343,13 @@ module ActiveRecord 
     | 
|
| 
       413 
343 
     | 
    
         
             
                    end
         
     | 
| 
       414 
344 
     | 
    
         
             
                  end
         
     | 
| 
       415 
345 
     | 
    
         | 
| 
       416 
     | 
    
         
            -
                  def  
     | 
| 
      
 346 
     | 
    
         
            +
                  def primary_keys(table_name) # :nodoc:
         
     | 
| 
       417 
347 
     | 
    
         
             
                    pks = table_structure(table_name).select { |f| f['pk'] > 0 }
         
     | 
| 
       418 
     | 
    
         
            -
                     
     | 
| 
       419 
     | 
    
         
            -
                    pks[0]['name']
         
     | 
| 
      
 348 
     | 
    
         
            +
                    pks.sort_by { |f| f['pk'] }.map { |f| f['name'] }
         
     | 
| 
       420 
349 
     | 
    
         
             
                  end
         
     | 
| 
       421 
350 
     | 
    
         | 
| 
       422 
     | 
    
         
            -
                  def remove_index 
     | 
| 
      
 351 
     | 
    
         
            +
                  def remove_index(table_name, options = {}) #:nodoc:
         
     | 
| 
      
 352 
     | 
    
         
            +
                    index_name = index_name_for_remove(table_name, options)
         
     | 
| 
       423 
353 
     | 
    
         
             
                    exec_query "DROP INDEX #{quote_column_name(index_name)}"
         
     | 
| 
       424 
354 
     | 
    
         
             
                  end
         
     | 
| 
       425 
355 
     | 
    
         | 
| 
         @@ -454,13 +384,15 @@ module ActiveRecord 
     | 
|
| 
       454 
384 
     | 
    
         
             
                    end
         
     | 
| 
       455 
385 
     | 
    
         
             
                  end
         
     | 
| 
       456 
386 
     | 
    
         | 
| 
       457 
     | 
    
         
            -
                  def change_column_default(table_name, column_name,  
     | 
| 
      
 387 
     | 
    
         
            +
                  def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
         
     | 
| 
      
 388 
     | 
    
         
            +
                    default = extract_new_default_value(default_or_changes)
         
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
       458 
390 
     | 
    
         
             
                    alter_table(table_name) do |definition|
         
     | 
| 
       459 
391 
     | 
    
         
             
                      definition[column_name].default = default
         
     | 
| 
       460 
392 
     | 
    
         
             
                    end
         
     | 
| 
       461 
393 
     | 
    
         
             
                  end
         
     | 
| 
       462 
394 
     | 
    
         | 
| 
       463 
     | 
    
         
            -
                  def change_column_null(table_name, column_name, null, default = nil)
         
     | 
| 
      
 395 
     | 
    
         
            +
                  def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
         
     | 
| 
       464 
396 
     | 
    
         
             
                    unless null || default.nil?
         
     | 
| 
       465 
397 
     | 
    
         
             
                      exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
         
     | 
| 
       466 
398 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -479,6 +411,7 @@ module ActiveRecord 
     | 
|
| 
       479 
411 
     | 
    
         
             
                        self.null    = options[:null] if options.include?(:null)
         
     | 
| 
       480 
412 
     | 
    
         
             
                        self.precision = options[:precision] if options.include?(:precision)
         
     | 
| 
       481 
413 
     | 
    
         
             
                        self.scale   = options[:scale] if options.include?(:scale)
         
     | 
| 
      
 414 
     | 
    
         
            +
                        self.collation = options[:collation] if options.include?(:collation)
         
     | 
| 
       482 
415 
     | 
    
         
             
                      end
         
     | 
| 
       483 
416 
     | 
    
         
             
                    end
         
     | 
| 
       484 
417 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -491,15 +424,10 @@ module ActiveRecord 
     | 
|
| 
       491 
424 
     | 
    
         | 
| 
       492 
425 
     | 
    
         
             
                  protected
         
     | 
| 
       493 
426 
     | 
    
         | 
| 
       494 
     | 
    
         
            -
                    def initialize_type_map(m)
         
     | 
| 
       495 
     | 
    
         
            -
                      super
         
     | 
| 
       496 
     | 
    
         
            -
                      m.register_type(/binary/i, SQLite3Binary.new)
         
     | 
| 
       497 
     | 
    
         
            -
                    end
         
     | 
| 
       498 
     | 
    
         
            -
             
     | 
| 
       499 
427 
     | 
    
         
             
                    def table_structure(table_name)
         
     | 
| 
       500 
     | 
    
         
            -
                      structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", 'SCHEMA') 
     | 
| 
      
 428 
     | 
    
         
            +
                      structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", 'SCHEMA')
         
     | 
| 
       501 
429 
     | 
    
         
             
                      raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
         
     | 
| 
       502 
     | 
    
         
            -
                      structure
         
     | 
| 
      
 430 
     | 
    
         
            +
                      table_structure_with_collation(table_name, structure)
         
     | 
| 
       503 
431 
     | 
    
         
             
                    end
         
     | 
| 
       504 
432 
     | 
    
         | 
| 
       505 
433 
     | 
    
         
             
                    def alter_table(table_name, options = {}) #:nodoc:
         
     | 
| 
         @@ -534,13 +462,13 @@ module ActiveRecord 
     | 
|
| 
       534 
462 
     | 
    
         
             
                          @definition.column(column_name, column.type,
         
     | 
| 
       535 
463 
     | 
    
         
             
                            :limit => column.limit, :default => column.default,
         
     | 
| 
       536 
464 
     | 
    
         
             
                            :precision => column.precision, :scale => column.scale,
         
     | 
| 
       537 
     | 
    
         
            -
                            :null => column.null)
         
     | 
| 
      
 465 
     | 
    
         
            +
                            :null => column.null, collation: column.collation)
         
     | 
| 
       538 
466 
     | 
    
         
             
                        end
         
     | 
| 
       539 
467 
     | 
    
         
             
                        yield @definition if block_given?
         
     | 
| 
       540 
468 
     | 
    
         
             
                      end
         
     | 
| 
       541 
469 
     | 
    
         
             
                      copy_table_indexes(from, to, options[:rename] || {})
         
     | 
| 
       542 
470 
     | 
    
         
             
                      copy_table_contents(from, to,
         
     | 
| 
       543 
     | 
    
         
            -
                        @definition.columns.map 
     | 
| 
      
 471 
     | 
    
         
            +
                        @definition.columns.map(&:name),
         
     | 
| 
       544 
472 
     | 
    
         
             
                        options[:rename] || {})
         
     | 
| 
       545 
473 
     | 
    
         
             
                    end
         
     | 
| 
       546 
474 
     | 
    
         | 
| 
         @@ -553,7 +481,7 @@ module ActiveRecord 
     | 
|
| 
       553 
481 
     | 
    
         
             
                          name = name[1..-1]
         
     | 
| 
       554 
482 
     | 
    
         
             
                        end
         
     | 
| 
       555 
483 
     | 
    
         | 
| 
       556 
     | 
    
         
            -
                        to_column_names = columns(to).map 
     | 
| 
      
 484 
     | 
    
         
            +
                        to_column_names = columns(to).map(&:name)
         
     | 
| 
       557 
485 
     | 
    
         
             
                        columns = index.columns.map {|c| rename[c] || c }.select do |column|
         
     | 
| 
       558 
486 
     | 
    
         
             
                          to_column_names.include?(column)
         
     | 
| 
       559 
487 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -570,25 +498,14 @@ module ActiveRecord 
     | 
|
| 
       570 
498 
     | 
    
         
             
                    def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
         
     | 
| 
       571 
499 
     | 
    
         
             
                      column_mappings = Hash[columns.map {|name| [name, name]}]
         
     | 
| 
       572 
500 
     | 
    
         
             
                      rename.each { |a| column_mappings[a.last] = a.first }
         
     | 
| 
       573 
     | 
    
         
            -
                      from_columns = columns(from).collect 
     | 
| 
      
 501 
     | 
    
         
            +
                      from_columns = columns(from).collect(&:name)
         
     | 
| 
       574 
502 
     | 
    
         
             
                      columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
         
     | 
| 
      
 503 
     | 
    
         
            +
                      from_columns_to_copy = columns.map { |col| column_mappings[col] }
         
     | 
| 
       575 
504 
     | 
    
         
             
                      quoted_columns = columns.map { |col| quote_column_name(col) } * ','
         
     | 
| 
      
 505 
     | 
    
         
            +
                      quoted_from_columns = from_columns_to_copy.map { |col| quote_column_name(col) } * ','
         
     | 
| 
       576 
506 
     | 
    
         | 
| 
       577 
     | 
    
         
            -
                       
     | 
| 
       578 
     | 
    
         
            -
             
     | 
| 
       579 
     | 
    
         
            -
                      raw_column_mappings = Hash[columns(from).map { |c| [c.name, c] }]
         
     | 
| 
       580 
     | 
    
         
            -
             
     | 
| 
       581 
     | 
    
         
            -
                      exec_query("SELECT * FROM #{quote_table_name(from)}").each do |row|
         
     | 
| 
       582 
     | 
    
         
            -
                        sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
         
     | 
| 
       583 
     | 
    
         
            -
             
     | 
| 
       584 
     | 
    
         
            -
                        column_values = columns.map do |col|
         
     | 
| 
       585 
     | 
    
         
            -
                          quote(row[column_mappings[col]], raw_column_mappings[col])
         
     | 
| 
       586 
     | 
    
         
            -
                        end
         
     | 
| 
       587 
     | 
    
         
            -
             
     | 
| 
       588 
     | 
    
         
            -
                        sql << column_values * ', '
         
     | 
| 
       589 
     | 
    
         
            -
                        sql << ')'
         
     | 
| 
       590 
     | 
    
         
            -
                        exec_query sql
         
     | 
| 
       591 
     | 
    
         
            -
                      end
         
     | 
| 
      
 507 
     | 
    
         
            +
                      exec_query("INSERT INTO #{quote_table_name(to)} (#{quoted_columns})
         
     | 
| 
      
 508 
     | 
    
         
            +
                                 SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
         
     | 
| 
       592 
509 
     | 
    
         
             
                    end
         
     | 
| 
       593 
510 
     | 
    
         | 
| 
       594 
511 
     | 
    
         
             
                    def sqlite_version
         
     | 
| 
         @@ -602,11 +519,51 @@ module ActiveRecord 
     | 
|
| 
       602 
519 
     | 
    
         
             
                      # Older versions of SQLite return:
         
     | 
| 
       603 
520 
     | 
    
         
             
                      #   column *column_name* is not unique
         
     | 
| 
       604 
521 
     | 
    
         
             
                      when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
         
     | 
| 
       605 
     | 
    
         
            -
                        RecordNotUnique.new(message 
     | 
| 
      
 522 
     | 
    
         
            +
                        RecordNotUnique.new(message)
         
     | 
| 
       606 
523 
     | 
    
         
             
                      else
         
     | 
| 
       607 
524 
     | 
    
         
             
                        super
         
     | 
| 
       608 
525 
     | 
    
         
             
                      end
         
     | 
| 
       609 
526 
     | 
    
         
             
                    end
         
     | 
| 
      
 527 
     | 
    
         
            +
             
     | 
| 
      
 528 
     | 
    
         
            +
                  private
         
     | 
| 
      
 529 
     | 
    
         
            +
                    COLLATE_REGEX = /.*\"(\w+)\".*collate\s+\"(\w+)\".*/i.freeze
         
     | 
| 
      
 530 
     | 
    
         
            +
             
     | 
| 
      
 531 
     | 
    
         
            +
                    def table_structure_with_collation(table_name, basic_structure)
         
     | 
| 
      
 532 
     | 
    
         
            +
                      collation_hash = {}
         
     | 
| 
      
 533 
     | 
    
         
            +
                      sql            = "SELECT sql FROM
         
     | 
| 
      
 534 
     | 
    
         
            +
                                          (SELECT * FROM sqlite_master UNION ALL
         
     | 
| 
      
 535 
     | 
    
         
            +
                                           SELECT * FROM sqlite_temp_master)
         
     | 
| 
      
 536 
     | 
    
         
            +
                                        WHERE type='table' and name='#{ table_name }' \;"
         
     | 
| 
      
 537 
     | 
    
         
            +
             
     | 
| 
      
 538 
     | 
    
         
            +
                      # Result will have following sample string
         
     | 
| 
      
 539 
     | 
    
         
            +
                      # CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
         
     | 
| 
      
 540 
     | 
    
         
            +
                      #                       "password_digest" varchar COLLATE "NOCASE");
         
     | 
| 
      
 541 
     | 
    
         
            +
                      result = exec_query(sql, 'SCHEMA').first
         
     | 
| 
      
 542 
     | 
    
         
            +
             
     | 
| 
      
 543 
     | 
    
         
            +
                      if result
         
     | 
| 
      
 544 
     | 
    
         
            +
                        # Splitting with left parentheses and picking up last will return all
         
     | 
| 
      
 545 
     | 
    
         
            +
                        # columns separated with comma(,).
         
     | 
| 
      
 546 
     | 
    
         
            +
                        columns_string = result["sql"].split('(').last
         
     | 
| 
      
 547 
     | 
    
         
            +
             
     | 
| 
      
 548 
     | 
    
         
            +
                        columns_string.split(',').each do |column_string|
         
     | 
| 
      
 549 
     | 
    
         
            +
                          # This regex will match the column name and collation type and will save
         
     | 
| 
      
 550 
     | 
    
         
            +
                          # the value in $1 and $2 respectively.
         
     | 
| 
      
 551 
     | 
    
         
            +
                          collation_hash[$1] = $2 if (COLLATE_REGEX =~ column_string)
         
     | 
| 
      
 552 
     | 
    
         
            +
                        end
         
     | 
| 
      
 553 
     | 
    
         
            +
             
     | 
| 
      
 554 
     | 
    
         
            +
                        basic_structure.map! do |column|
         
     | 
| 
      
 555 
     | 
    
         
            +
                          column_name = column['name']
         
     | 
| 
      
 556 
     | 
    
         
            +
             
     | 
| 
      
 557 
     | 
    
         
            +
                          if collation_hash.has_key? column_name
         
     | 
| 
      
 558 
     | 
    
         
            +
                            column['collation'] = collation_hash[column_name]
         
     | 
| 
      
 559 
     | 
    
         
            +
                          end
         
     | 
| 
      
 560 
     | 
    
         
            +
             
     | 
| 
      
 561 
     | 
    
         
            +
                          column
         
     | 
| 
      
 562 
     | 
    
         
            +
                        end
         
     | 
| 
      
 563 
     | 
    
         
            +
                      else
         
     | 
| 
      
 564 
     | 
    
         
            +
                        basic_structure.to_hash
         
     | 
| 
      
 565 
     | 
    
         
            +
                      end
         
     | 
| 
      
 566 
     | 
    
         
            +
                    end
         
     | 
| 
       610 
567 
     | 
    
         
             
                end
         
     | 
| 
       611 
568 
     | 
    
         
             
              end
         
     | 
| 
       612 
569 
     | 
    
         
             
            end
         
     |