activerecord 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +7 -0
 - data/CHANGELOG.md +2102 -0
 - data/MIT-LICENSE +20 -0
 - data/README.rdoc +35 -44
 - data/examples/performance.rb +110 -100
 - data/lib/active_record/aggregations.rb +59 -75
 - data/lib/active_record/associations/alias_tracker.rb +76 -0
 - data/lib/active_record/associations/association.rb +248 -0
 - data/lib/active_record/associations/association_scope.rb +135 -0
 - data/lib/active_record/associations/belongs_to_association.rb +60 -59
 - data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -59
 - data/lib/active_record/associations/builder/association.rb +108 -0
 - data/lib/active_record/associations/builder/belongs_to.rb +98 -0
 - data/lib/active_record/associations/builder/collection_association.rb +89 -0
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
 - data/lib/active_record/associations/builder/has_many.rb +15 -0
 - data/lib/active_record/associations/builder/has_one.rb +25 -0
 - data/lib/active_record/associations/builder/singular_association.rb +32 -0
 - data/lib/active_record/associations/collection_association.rb +608 -0
 - data/lib/active_record/associations/collection_proxy.rb +986 -0
 - data/lib/active_record/associations/has_and_belongs_to_many_association.rb +40 -112
 - data/lib/active_record/associations/has_many_association.rb +83 -76
 - data/lib/active_record/associations/has_many_through_association.rb +147 -66
 - data/lib/active_record/associations/has_one_association.rb +67 -108
 - data/lib/active_record/associations/has_one_through_association.rb +21 -25
 - data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
 - data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
 - data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
 - data/lib/active_record/associations/join_dependency.rb +235 -0
 - data/lib/active_record/associations/join_helper.rb +45 -0
 - data/lib/active_record/associations/preloader/association.rb +121 -0
 - data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
 - data/lib/active_record/associations/preloader/collection_association.rb +24 -0
 - data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
 - data/lib/active_record/associations/preloader/has_many.rb +17 -0
 - data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
 - data/lib/active_record/associations/preloader/has_one.rb +23 -0
 - data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
 - data/lib/active_record/associations/preloader/singular_association.rb +21 -0
 - data/lib/active_record/associations/preloader/through_association.rb +63 -0
 - data/lib/active_record/associations/preloader.rb +178 -0
 - data/lib/active_record/associations/singular_association.rb +64 -0
 - data/lib/active_record/associations/through_association.rb +87 -0
 - data/lib/active_record/associations.rb +512 -1224
 - data/lib/active_record/attribute_assignment.rb +201 -0
 - data/lib/active_record/attribute_methods/before_type_cast.rb +49 -12
 - data/lib/active_record/attribute_methods/dirty.rb +51 -28
 - data/lib/active_record/attribute_methods/primary_key.rb +94 -22
 - data/lib/active_record/attribute_methods/query.rb +5 -4
 - data/lib/active_record/attribute_methods/read.rb +63 -72
 - data/lib/active_record/attribute_methods/serialization.rb +162 -0
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -41
 - data/lib/active_record/attribute_methods/write.rb +39 -13
 - data/lib/active_record/attribute_methods.rb +362 -29
 - data/lib/active_record/autosave_association.rb +132 -75
 - data/lib/active_record/base.rb +83 -1627
 - data/lib/active_record/callbacks.rb +69 -47
 - data/lib/active_record/coders/yaml_column.rb +38 -0
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +411 -138
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +21 -11
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -173
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -22
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +82 -25
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +176 -414
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +562 -232
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +281 -53
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
 - data/lib/active_record/connection_adapters/column.rb +318 -0
 - data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
 - data/lib/active_record/connection_adapters/mysql_adapter.rb +365 -450
 - data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
 - data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +672 -752
 - data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +588 -17
 - data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
 - data/lib/active_record/connection_handling.rb +98 -0
 - data/lib/active_record/core.rb +463 -0
 - data/lib/active_record/counter_cache.rb +108 -101
 - data/lib/active_record/dynamic_matchers.rb +131 -0
 - data/lib/active_record/errors.rb +54 -13
 - data/lib/active_record/explain.rb +38 -0
 - data/lib/active_record/explain_registry.rb +30 -0
 - data/lib/active_record/explain_subscriber.rb +29 -0
 - data/lib/active_record/fixture_set/file.rb +55 -0
 - data/lib/active_record/fixtures.rb +703 -785
 - data/lib/active_record/inheritance.rb +200 -0
 - data/lib/active_record/integration.rb +60 -0
 - data/lib/active_record/locale/en.yml +8 -1
 - data/lib/active_record/locking/optimistic.rb +69 -60
 - data/lib/active_record/locking/pessimistic.rb +34 -12
 - data/lib/active_record/log_subscriber.rb +40 -6
 - data/lib/active_record/migration/command_recorder.rb +164 -0
 - data/lib/active_record/migration/join_table.rb +15 -0
 - data/lib/active_record/migration.rb +614 -216
 - data/lib/active_record/model_schema.rb +345 -0
 - data/lib/active_record/nested_attributes.rb +248 -119
 - data/lib/active_record/null_relation.rb +65 -0
 - data/lib/active_record/persistence.rb +275 -57
 - data/lib/active_record/query_cache.rb +29 -9
 - data/lib/active_record/querying.rb +62 -0
 - data/lib/active_record/railtie.rb +135 -21
 - data/lib/active_record/railties/console_sandbox.rb +5 -0
 - data/lib/active_record/railties/controller_runtime.rb +17 -5
 - data/lib/active_record/railties/databases.rake +249 -359
 - data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
 - data/lib/active_record/readonly_attributes.rb +30 -0
 - data/lib/active_record/reflection.rb +283 -103
 - data/lib/active_record/relation/batches.rb +38 -34
 - data/lib/active_record/relation/calculations.rb +252 -139
 - data/lib/active_record/relation/delegation.rb +125 -0
 - data/lib/active_record/relation/finder_methods.rb +182 -188
 - data/lib/active_record/relation/merger.rb +161 -0
 - data/lib/active_record/relation/predicate_builder.rb +86 -21
 - data/lib/active_record/relation/query_methods.rb +917 -134
 - data/lib/active_record/relation/spawn_methods.rb +53 -92
 - data/lib/active_record/relation.rb +405 -143
 - data/lib/active_record/result.rb +67 -0
 - data/lib/active_record/runtime_registry.rb +17 -0
 - data/lib/active_record/sanitization.rb +168 -0
 - data/lib/active_record/schema.rb +20 -14
 - data/lib/active_record/schema_dumper.rb +55 -46
 - data/lib/active_record/schema_migration.rb +39 -0
 - data/lib/active_record/scoping/default.rb +146 -0
 - data/lib/active_record/scoping/named.rb +175 -0
 - data/lib/active_record/scoping.rb +82 -0
 - data/lib/active_record/serialization.rb +8 -46
 - data/lib/active_record/serializers/xml_serializer.rb +21 -68
 - data/lib/active_record/statement_cache.rb +26 -0
 - data/lib/active_record/store.rb +156 -0
 - data/lib/active_record/tasks/database_tasks.rb +203 -0
 - data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
 - data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
 - data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
 - data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
 - data/lib/active_record/test_case.rb +57 -28
 - data/lib/active_record/timestamp.rb +49 -18
 - data/lib/active_record/transactions.rb +106 -63
 - data/lib/active_record/translation.rb +22 -0
 - data/lib/active_record/validations/associated.rb +25 -24
 - data/lib/active_record/validations/presence.rb +65 -0
 - data/lib/active_record/validations/uniqueness.rb +123 -83
 - data/lib/active_record/validations.rb +29 -29
 - data/lib/active_record/version.rb +7 -5
 - data/lib/active_record.rb +83 -34
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +46 -9
 - data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
 - data/lib/rails/generators/active_record/migration/templates/migration.rb +30 -8
 - data/lib/rails/generators/active_record/model/model_generator.rb +15 -5
 - data/lib/rails/generators/active_record/model/templates/model.rb +7 -2
 - data/lib/rails/generators/active_record/model/templates/module.rb +3 -1
 - data/lib/rails/generators/active_record.rb +4 -8
 - metadata +163 -121
 - data/CHANGELOG +0 -6023
 - data/examples/associations.png +0 -0
 - data/lib/active_record/association_preload.rb +0 -403
 - data/lib/active_record/associations/association_collection.rb +0 -562
 - data/lib/active_record/associations/association_proxy.rb +0 -295
 - data/lib/active_record/associations/through_association_scope.rb +0 -154
 - data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -113
 - data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -401
 - data/lib/active_record/dynamic_finder_match.rb +0 -53
 - data/lib/active_record/dynamic_scope_match.rb +0 -32
 - data/lib/active_record/named_scope.rb +0 -138
 - data/lib/active_record/observer.rb +0 -140
 - data/lib/active_record/session_store.rb +0 -340
 - data/lib/rails/generators/active_record/model/templates/migration.rb +0 -16
 - data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
 - data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -2
 - data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -24
 - data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
 
| 
         @@ -1,10 +1,12 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require ' 
     | 
| 
      
 1 
     | 
    
         
            +
            require 'active_record/migration/join_table'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       4 
4 
     | 
    
         
             
              module ConnectionAdapters # :nodoc:
         
     | 
| 
       5 
5 
     | 
    
         
             
                module SchemaStatements
         
     | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
      
 6 
     | 
    
         
            +
                  include ActiveRecord::Migration::JoinTable
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # Returns a hash of mappings from the abstract data types to the native
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # database types. See TableDefinition#column for details on the recognized
         
     | 
| 
       8 
10 
     | 
    
         
             
                  # abstract data types.
         
     | 
| 
       9 
11 
     | 
    
         
             
                  def native_database_types
         
     | 
| 
       10 
12 
     | 
    
         
             
                    {}
         
     | 
| 
         @@ -12,11 +14,13 @@ module ActiveRecord 
     | 
|
| 
       12 
14 
     | 
    
         | 
| 
       13 
15 
     | 
    
         
             
                  # Truncates a table alias according to the limits of the current adapter.
         
     | 
| 
       14 
16 
     | 
    
         
             
                  def table_alias_for(table_name)
         
     | 
| 
       15 
     | 
    
         
            -
                    table_name[0 
     | 
| 
      
 17 
     | 
    
         
            +
                    table_name[0...table_alias_length].tr('.', '_')
         
     | 
| 
       16 
18 
     | 
    
         
             
                  end
         
     | 
| 
       17 
19 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                  #  
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
                  # Checks to see if the table +table_name+ exists on the database.
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #   table_exists?(:developers)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #
         
     | 
| 
       20 
24 
     | 
    
         
             
                  def table_exists?(table_name)
         
     | 
| 
       21 
25 
     | 
    
         
             
                    tables.include?(table_name.to_s)
         
     | 
| 
       22 
26 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -24,22 +28,22 @@ module ActiveRecord 
     | 
|
| 
       24 
28 
     | 
    
         
             
                  # Returns an array of indexes for the given table.
         
     | 
| 
       25 
29 
     | 
    
         
             
                  # def indexes(table_name, name = nil) end
         
     | 
| 
       26 
30 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                  # Checks to see if an index exists on a table for a given index definition
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # Checks to see if an index exists on a table for a given index definition.
         
     | 
| 
       28 
32 
     | 
    
         
             
                  #
         
     | 
| 
       29 
     | 
    
         
            -
                  #  
     | 
| 
       30 
     | 
    
         
            -
                  # 
     | 
| 
       31 
     | 
    
         
            -
                  #  index_exists?(:suppliers, :company_id)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #   # Check an index exists
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #   index_exists?(:suppliers, :company_id)
         
     | 
| 
       32 
35 
     | 
    
         
             
                  #
         
     | 
| 
       33 
     | 
    
         
            -
                  # 
     | 
| 
       34 
     | 
    
         
            -
                  # 
     | 
| 
      
 36 
     | 
    
         
            +
                  #   # Check an index on multiple columns exists
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #   index_exists?(:suppliers, [:company_id, :company_type])
         
     | 
| 
       35 
38 
     | 
    
         
             
                  #
         
     | 
| 
       36 
     | 
    
         
            -
                  # 
     | 
| 
       37 
     | 
    
         
            -
                  # 
     | 
| 
      
 39 
     | 
    
         
            +
                  #   # Check a unique index exists
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #   index_exists?(:suppliers, :company_id, unique: true)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  #
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #   # Check an index with a custom name exists
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #   index_exists?(:suppliers, :company_id, name: "idx_company_id"
         
     | 
| 
       38 
44 
     | 
    
         
             
                  #
         
     | 
| 
       39 
     | 
    
         
            -
                  #  # Check an index with a custom name exists
         
     | 
| 
       40 
     | 
    
         
            -
                  #  index_exists?(:suppliers, :company_id, :name => "idx_company_id"
         
     | 
| 
       41 
45 
     | 
    
         
             
                  def index_exists?(table_name, column_name, options = {})
         
     | 
| 
       42 
     | 
    
         
            -
                    column_names = Array 
     | 
| 
      
 46 
     | 
    
         
            +
                    column_names = Array(column_name)
         
     | 
| 
       43 
47 
     | 
    
         
             
                    index_name = options.key?(:name) ? options[:name].to_s : index_name(table_name, :column => column_names)
         
     | 
| 
       44 
48 
     | 
    
         
             
                    if options[:unique]
         
     | 
| 
       45 
49 
     | 
    
         
             
                      indexes(table_name).any?{ |i| i.unique && i.name == index_name }
         
     | 
| 
         @@ -50,55 +54,63 @@ module ActiveRecord 
     | 
|
| 
       50 
54 
     | 
    
         | 
| 
       51 
55 
     | 
    
         
             
                  # Returns an array of Column objects for the table specified by +table_name+.
         
     | 
| 
       52 
56 
     | 
    
         
             
                  # See the concrete implementation for details on the expected parameter values.
         
     | 
| 
       53 
     | 
    
         
            -
                  def columns(table_name 
     | 
| 
      
 57 
     | 
    
         
            +
                  def columns(table_name) end
         
     | 
| 
       54 
58 
     | 
    
         | 
| 
       55 
59 
     | 
    
         
             
                  # Checks to see if a column exists in a given table.
         
     | 
| 
       56 
60 
     | 
    
         
             
                  #
         
     | 
| 
       57 
     | 
    
         
            -
                  #  
     | 
| 
       58 
     | 
    
         
            -
                  # 
     | 
| 
       59 
     | 
    
         
            -
                  # 
     | 
| 
      
 61 
     | 
    
         
            +
                  #   # Check a column exists
         
     | 
| 
      
 62 
     | 
    
         
            +
                  #   column_exists?(:suppliers, :name)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  #
         
     | 
| 
      
 64 
     | 
    
         
            +
                  #   # Check a column exists of a particular type
         
     | 
| 
      
 65 
     | 
    
         
            +
                  #   column_exists?(:suppliers, :name, :string)
         
     | 
| 
       60 
66 
     | 
    
         
             
                  #
         
     | 
| 
       61 
     | 
    
         
            -
                  # 
     | 
| 
       62 
     | 
    
         
            -
                  # 
     | 
| 
      
 67 
     | 
    
         
            +
                  #   # Check a column exists with a specific definition
         
     | 
| 
      
 68 
     | 
    
         
            +
                  #   column_exists?(:suppliers, :name, :string, limit: 100)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  #   column_exists?(:suppliers, :name, :string, default: 'default')
         
     | 
| 
      
 70 
     | 
    
         
            +
                  #   column_exists?(:suppliers, :name, :string, null: false)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  #   column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
         
     | 
| 
       63 
72 
     | 
    
         
             
                  #
         
     | 
| 
       64 
     | 
    
         
            -
                  #  # Check a column exists with a specific definition
         
     | 
| 
       65 
     | 
    
         
            -
                  #  column_exists?(:suppliers, :name, :string, :limit => 100)
         
     | 
| 
       66 
73 
     | 
    
         
             
                  def column_exists?(table_name, column_name, type = nil, options = {})
         
     | 
| 
       67 
74 
     | 
    
         
             
                    columns(table_name).any?{ |c| c.name == column_name.to_s &&
         
     | 
| 
       68 
     | 
    
         
            -
                                                  (!type 
     | 
| 
       69 
     | 
    
         
            -
                                                  (!options 
     | 
| 
       70 
     | 
    
         
            -
                                                  (!options 
     | 
| 
       71 
     | 
    
         
            -
                                                  (!options 
     | 
| 
      
 75 
     | 
    
         
            +
                                                  (!type                     || c.type == type) &&
         
     | 
| 
      
 76 
     | 
    
         
            +
                                                  (!options.key?(:limit)     || c.limit == options[:limit]) &&
         
     | 
| 
      
 77 
     | 
    
         
            +
                                                  (!options.key?(:precision) || c.precision == options[:precision]) &&
         
     | 
| 
      
 78 
     | 
    
         
            +
                                                  (!options.key?(:scale)     || c.scale == options[:scale]) &&
         
     | 
| 
      
 79 
     | 
    
         
            +
                                                  (!options.key?(:default)   || c.default == options[:default]) &&
         
     | 
| 
      
 80 
     | 
    
         
            +
                                                  (!options.key?(:null)      || c.null == options[:null]) }
         
     | 
| 
       72 
81 
     | 
    
         
             
                  end
         
     | 
| 
       73 
82 
     | 
    
         | 
| 
       74 
83 
     | 
    
         
             
                  # Creates a new table with the name +table_name+. +table_name+ may either
         
     | 
| 
       75 
84 
     | 
    
         
             
                  # be a String or a Symbol.
         
     | 
| 
       76 
85 
     | 
    
         
             
                  #
         
     | 
| 
       77 
     | 
    
         
            -
                  # There are two ways to work with +create_table+. 
     | 
| 
      
 86 
     | 
    
         
            +
                  # There are two ways to work with +create_table+. You can use the block
         
     | 
| 
       78 
87 
     | 
    
         
             
                  # form or the regular form, like this:
         
     | 
| 
       79 
88 
     | 
    
         
             
                  #
         
     | 
| 
       80 
89 
     | 
    
         
             
                  # === Block form
         
     | 
| 
       81 
     | 
    
         
            -
                  #  # create_table() passes a TableDefinition object to the block.
         
     | 
| 
       82 
     | 
    
         
            -
                  #  # This form will not only create the table, but also columns for the
         
     | 
| 
       83 
     | 
    
         
            -
                  #  # table.
         
     | 
| 
       84 
90 
     | 
    
         
             
                  #
         
     | 
| 
       85 
     | 
    
         
            -
                  # 
     | 
| 
       86 
     | 
    
         
            -
                  # 
     | 
| 
       87 
     | 
    
         
            -
                  # 
     | 
| 
       88 
     | 
    
         
            -
                  # 
     | 
| 
      
 91 
     | 
    
         
            +
                  #   # create_table() passes a TableDefinition object to the block.
         
     | 
| 
      
 92 
     | 
    
         
            +
                  #   # This form will not only create the table, but also columns for the
         
     | 
| 
      
 93 
     | 
    
         
            +
                  #   # table.
         
     | 
| 
      
 94 
     | 
    
         
            +
                  #
         
     | 
| 
      
 95 
     | 
    
         
            +
                  #   create_table(:suppliers) do |t|
         
     | 
| 
      
 96 
     | 
    
         
            +
                  #     t.column :name, :string, limit: 60
         
     | 
| 
      
 97 
     | 
    
         
            +
                  #     # Other fields here
         
     | 
| 
      
 98 
     | 
    
         
            +
                  #   end
         
     | 
| 
       89 
99 
     | 
    
         
             
                  #
         
     | 
| 
       90 
100 
     | 
    
         
             
                  # === Block form, with shorthand
         
     | 
| 
       91 
     | 
    
         
            -
                  # 
     | 
| 
       92 
     | 
    
         
            -
                  # 
     | 
| 
       93 
     | 
    
         
            -
                  # 
     | 
| 
       94 
     | 
    
         
            -
                  # 
     | 
| 
       95 
     | 
    
         
            -
                  # 
     | 
| 
      
 101 
     | 
    
         
            +
                  #
         
     | 
| 
      
 102 
     | 
    
         
            +
                  #   # You can also use the column types as method calls, rather than calling the column method.
         
     | 
| 
      
 103 
     | 
    
         
            +
                  #   create_table(:suppliers) do |t|
         
     | 
| 
      
 104 
     | 
    
         
            +
                  #     t.string :name, limit: 60
         
     | 
| 
      
 105 
     | 
    
         
            +
                  #     # Other fields here
         
     | 
| 
      
 106 
     | 
    
         
            +
                  #   end
         
     | 
| 
       96 
107 
     | 
    
         
             
                  #
         
     | 
| 
       97 
108 
     | 
    
         
             
                  # === Regular form
         
     | 
| 
       98 
     | 
    
         
            -
                  # 
     | 
| 
       99 
     | 
    
         
            -
                  # 
     | 
| 
       100 
     | 
    
         
            -
                  # 
     | 
| 
       101 
     | 
    
         
            -
                  # 
     | 
| 
      
 109 
     | 
    
         
            +
                  #
         
     | 
| 
      
 110 
     | 
    
         
            +
                  #   # Creates a table called 'suppliers' with no columns.
         
     | 
| 
      
 111 
     | 
    
         
            +
                  #   create_table(:suppliers)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  #   # Add a column to 'suppliers'.
         
     | 
| 
      
 113 
     | 
    
         
            +
                  #   add_column(:suppliers, :name, :string, {limit: 60})
         
     | 
| 
       102 
114 
     | 
    
         
             
                  #
         
     | 
| 
       103 
115 
     | 
    
         
             
                  # The +options+ hash can include the following keys:
         
     | 
| 
       104 
116 
     | 
    
         
             
                  # [<tt>:id</tt>]
         
     | 
| 
         @@ -109,7 +121,7 @@ module ActiveRecord 
     | 
|
| 
       109 
121 
     | 
    
         
             
                  #   Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
         
     | 
| 
       110 
122 
     | 
    
         
             
                  #
         
     | 
| 
       111 
123 
     | 
    
         
             
                  #   Also note that this just sets the primary key in the table. You additionally
         
     | 
| 
       112 
     | 
    
         
            -
                  #   need to configure the primary key in the model via  
     | 
| 
      
 124 
     | 
    
         
            +
                  #   need to configure the primary key in the model via +self.primary_key=+.
         
     | 
| 
       113 
125 
     | 
    
         
             
                  #   Models do NOT auto-detect the primary key from their table definition.
         
     | 
| 
       114 
126 
     | 
    
         
             
                  #
         
     | 
| 
       115 
127 
     | 
    
         
             
                  # [<tt>:options</tt>]
         
     | 
| 
         @@ -120,122 +132,222 @@ module ActiveRecord 
     | 
|
| 
       120 
132 
     | 
    
         
             
                  #   Set to true to drop the table before creating it.
         
     | 
| 
       121 
133 
     | 
    
         
             
                  #   Defaults to false.
         
     | 
| 
       122 
134 
     | 
    
         
             
                  #
         
     | 
| 
       123 
     | 
    
         
            -
                  # ===== Examples
         
     | 
| 
       124 
135 
     | 
    
         
             
                  # ====== Add a backend specific option to the generated SQL (MySQL)
         
     | 
| 
       125 
     | 
    
         
            -
                  # 
     | 
| 
      
 136 
     | 
    
         
            +
                  #
         
     | 
| 
      
 137 
     | 
    
         
            +
                  #   create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
         
     | 
| 
      
 138 
     | 
    
         
            +
                  #
         
     | 
| 
       126 
139 
     | 
    
         
             
                  # generates:
         
     | 
| 
       127 
     | 
    
         
            -
                  # 
     | 
| 
       128 
     | 
    
         
            -
                  # 
     | 
| 
       129 
     | 
    
         
            -
                  # 
     | 
| 
      
 140 
     | 
    
         
            +
                  #
         
     | 
| 
      
 141 
     | 
    
         
            +
                  #   CREATE TABLE suppliers (
         
     | 
| 
      
 142 
     | 
    
         
            +
                  #     id int(11) DEFAULT NULL auto_increment PRIMARY KEY
         
     | 
| 
      
 143 
     | 
    
         
            +
                  #   ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         
     | 
| 
       130 
144 
     | 
    
         
             
                  #
         
     | 
| 
       131 
145 
     | 
    
         
             
                  # ====== Rename the primary key column
         
     | 
| 
       132 
     | 
    
         
            -
                  # 
     | 
| 
       133 
     | 
    
         
            -
                  # 
     | 
| 
       134 
     | 
    
         
            -
                  # 
     | 
| 
      
 146 
     | 
    
         
            +
                  #
         
     | 
| 
      
 147 
     | 
    
         
            +
                  #   create_table(:objects, primary_key: 'guid') do |t|
         
     | 
| 
      
 148 
     | 
    
         
            +
                  #     t.column :name, :string, limit: 80
         
     | 
| 
      
 149 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 150 
     | 
    
         
            +
                  #
         
     | 
| 
       135 
151 
     | 
    
         
             
                  # generates:
         
     | 
| 
       136 
     | 
    
         
            -
                  # 
     | 
| 
       137 
     | 
    
         
            -
                  # 
     | 
| 
       138 
     | 
    
         
            -
                  # 
     | 
| 
       139 
     | 
    
         
            -
                  # 
     | 
| 
      
 152 
     | 
    
         
            +
                  #
         
     | 
| 
      
 153 
     | 
    
         
            +
                  #   CREATE TABLE objects (
         
     | 
| 
      
 154 
     | 
    
         
            +
                  #     guid int(11) DEFAULT NULL auto_increment PRIMARY KEY,
         
     | 
| 
      
 155 
     | 
    
         
            +
                  #     name varchar(80)
         
     | 
| 
      
 156 
     | 
    
         
            +
                  #   )
         
     | 
| 
       140 
157 
     | 
    
         
             
                  #
         
     | 
| 
       141 
158 
     | 
    
         
             
                  # ====== Do not add a primary key column
         
     | 
| 
       142 
     | 
    
         
            -
                  # 
     | 
| 
       143 
     | 
    
         
            -
                  # 
     | 
| 
       144 
     | 
    
         
            -
                  # 
     | 
| 
       145 
     | 
    
         
            -
                  # 
     | 
| 
      
 159 
     | 
    
         
            +
                  #
         
     | 
| 
      
 160 
     | 
    
         
            +
                  #   create_table(:categories_suppliers, id: false) do |t|
         
     | 
| 
      
 161 
     | 
    
         
            +
                  #     t.column :category_id, :integer
         
     | 
| 
      
 162 
     | 
    
         
            +
                  #     t.column :supplier_id, :integer
         
     | 
| 
      
 163 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 164 
     | 
    
         
            +
                  #
         
     | 
| 
       146 
165 
     | 
    
         
             
                  # generates:
         
     | 
| 
       147 
     | 
    
         
            -
                  # 
     | 
| 
       148 
     | 
    
         
            -
                  # 
     | 
| 
       149 
     | 
    
         
            -
                  # 
     | 
| 
       150 
     | 
    
         
            -
                  # 
     | 
| 
      
 166 
     | 
    
         
            +
                  #
         
     | 
| 
      
 167 
     | 
    
         
            +
                  #   CREATE TABLE categories_suppliers (
         
     | 
| 
      
 168 
     | 
    
         
            +
                  #     category_id int,
         
     | 
| 
      
 169 
     | 
    
         
            +
                  #     supplier_id int
         
     | 
| 
      
 170 
     | 
    
         
            +
                  #   )
         
     | 
| 
       151 
171 
     | 
    
         
             
                  #
         
     | 
| 
       152 
172 
     | 
    
         
             
                  # See also TableDefinition#column for details on how to create columns.
         
     | 
| 
       153 
173 
     | 
    
         
             
                  def create_table(table_name, options = {})
         
     | 
| 
       154 
     | 
    
         
            -
                     
     | 
| 
       155 
     | 
    
         
            -
                    table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
         
     | 
| 
      
 174 
     | 
    
         
            +
                    td = create_table_definition table_name, options[:temporary], options[:options]
         
     | 
| 
       156 
175 
     | 
    
         | 
| 
       157 
     | 
    
         
            -
                     
     | 
| 
      
 176 
     | 
    
         
            +
                    unless options[:id] == false
         
     | 
| 
      
 177 
     | 
    
         
            +
                      pk = options.fetch(:primary_key) {
         
     | 
| 
      
 178 
     | 
    
         
            +
                        Base.get_primary_key table_name.to_s.singularize
         
     | 
| 
      
 179 
     | 
    
         
            +
                      }
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                      td.primary_key pk, options.fetch(:id, :primary_key), options
         
     | 
| 
      
 182 
     | 
    
         
            +
                    end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                    yield td if block_given?
         
     | 
| 
       158 
185 
     | 
    
         | 
| 
       159 
186 
     | 
    
         
             
                    if options[:force] && table_exists?(table_name)
         
     | 
| 
       160 
187 
     | 
    
         
             
                      drop_table(table_name, options)
         
     | 
| 
       161 
188 
     | 
    
         
             
                    end
         
     | 
| 
       162 
189 
     | 
    
         | 
| 
       163 
     | 
    
         
            -
                     
     | 
| 
       164 
     | 
    
         
            -
                     
     | 
| 
       165 
     | 
    
         
            -
             
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
             
     | 
| 
      
 190 
     | 
    
         
            +
                    execute schema_creation.accept td
         
     | 
| 
      
 191 
     | 
    
         
            +
                    td.indexes.each_pair { |c,o| add_index table_name, c, o }
         
     | 
| 
      
 192 
     | 
    
         
            +
                  end
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                  # Creates a new join table with the name created using the lexical order of the first two
         
     | 
| 
      
 195 
     | 
    
         
            +
                  # arguments. These arguments can be a String or a Symbol.
         
     | 
| 
      
 196 
     | 
    
         
            +
                  #
         
     | 
| 
      
 197 
     | 
    
         
            +
                  #   # Creates a table called 'assemblies_parts' with no id.
         
     | 
| 
      
 198 
     | 
    
         
            +
                  #   create_join_table(:assemblies, :parts)
         
     | 
| 
      
 199 
     | 
    
         
            +
                  #
         
     | 
| 
      
 200 
     | 
    
         
            +
                  # You can pass a +options+ hash can include the following keys:
         
     | 
| 
      
 201 
     | 
    
         
            +
                  # [<tt>:table_name</tt>]
         
     | 
| 
      
 202 
     | 
    
         
            +
                  #   Sets the table name overriding the default
         
     | 
| 
      
 203 
     | 
    
         
            +
                  # [<tt>:column_options</tt>]
         
     | 
| 
      
 204 
     | 
    
         
            +
                  #   Any extra options you want appended to the columns definition.
         
     | 
| 
      
 205 
     | 
    
         
            +
                  # [<tt>:options</tt>]
         
     | 
| 
      
 206 
     | 
    
         
            +
                  #   Any extra options you want appended to the table definition.
         
     | 
| 
      
 207 
     | 
    
         
            +
                  # [<tt>:temporary</tt>]
         
     | 
| 
      
 208 
     | 
    
         
            +
                  #   Make a temporary table.
         
     | 
| 
      
 209 
     | 
    
         
            +
                  # [<tt>:force</tt>]
         
     | 
| 
      
 210 
     | 
    
         
            +
                  #   Set to true to drop the table before creating it.
         
     | 
| 
      
 211 
     | 
    
         
            +
                  #   Defaults to false.
         
     | 
| 
      
 212 
     | 
    
         
            +
                  #
         
     | 
| 
      
 213 
     | 
    
         
            +
                  # Note that +create_join_table+ does not create any indices by default; you can use
         
     | 
| 
      
 214 
     | 
    
         
            +
                  # its block form to do so yourself:
         
     | 
| 
      
 215 
     | 
    
         
            +
                  #
         
     | 
| 
      
 216 
     | 
    
         
            +
                  #   create_join_table :products, :categories do |t|
         
     | 
| 
      
 217 
     | 
    
         
            +
                  #     t.index :product_id
         
     | 
| 
      
 218 
     | 
    
         
            +
                  #     t.index :category_id
         
     | 
| 
      
 219 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 220 
     | 
    
         
            +
                  #
         
     | 
| 
      
 221 
     | 
    
         
            +
                  # ====== Add a backend specific option to the generated SQL (MySQL)
         
     | 
| 
      
 222 
     | 
    
         
            +
                  #
         
     | 
| 
      
 223 
     | 
    
         
            +
                  #   create_join_table(:assemblies, :parts, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
         
     | 
| 
      
 224 
     | 
    
         
            +
                  #
         
     | 
| 
      
 225 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 226 
     | 
    
         
            +
                  #
         
     | 
| 
      
 227 
     | 
    
         
            +
                  #   CREATE TABLE assemblies_parts (
         
     | 
| 
      
 228 
     | 
    
         
            +
                  #     assembly_id int NOT NULL,
         
     | 
| 
      
 229 
     | 
    
         
            +
                  #     part_id int NOT NULL,
         
     | 
| 
      
 230 
     | 
    
         
            +
                  #   ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         
     | 
| 
      
 231 
     | 
    
         
            +
                  #
         
     | 
| 
      
 232 
     | 
    
         
            +
                  def create_join_table(table_1, table_2, options = {})
         
     | 
| 
      
 233 
     | 
    
         
            +
                    join_table_name = find_join_table_name(table_1, table_2, options)
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                    column_options = options.delete(:column_options) || {}
         
     | 
| 
      
 236 
     | 
    
         
            +
                    column_options.reverse_merge!(null: false)
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                    t1_column, t2_column = [table_1, table_2].map{ |t| t.to_s.singularize.foreign_key }
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
      
 240 
     | 
    
         
            +
                    create_table(join_table_name, options.merge!(id: false)) do |td|
         
     | 
| 
      
 241 
     | 
    
         
            +
                      td.integer t1_column, column_options
         
     | 
| 
      
 242 
     | 
    
         
            +
                      td.integer t2_column, column_options
         
     | 
| 
      
 243 
     | 
    
         
            +
                      yield td if block_given?
         
     | 
| 
      
 244 
     | 
    
         
            +
                    end
         
     | 
| 
      
 245 
     | 
    
         
            +
                  end
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
                  # Drops the join table specified by the given arguments.
         
     | 
| 
      
 248 
     | 
    
         
            +
                  # See +create_join_table+ for details.
         
     | 
| 
      
 249 
     | 
    
         
            +
                  #
         
     | 
| 
      
 250 
     | 
    
         
            +
                  # Although this command ignores the block if one is given, it can be helpful
         
     | 
| 
      
 251 
     | 
    
         
            +
                  # to provide one in a migration's +change+ method so it can be reverted.
         
     | 
| 
      
 252 
     | 
    
         
            +
                  # In that case, the block will be used by create_join_table.
         
     | 
| 
      
 253 
     | 
    
         
            +
                  def drop_join_table(table_1, table_2, options = {})
         
     | 
| 
      
 254 
     | 
    
         
            +
                    join_table_name = find_join_table_name(table_1, table_2, options)
         
     | 
| 
      
 255 
     | 
    
         
            +
                    drop_table(join_table_name)
         
     | 
| 
       168 
256 
     | 
    
         
             
                  end
         
     | 
| 
       169 
257 
     | 
    
         | 
| 
       170 
258 
     | 
    
         
             
                  # A block for changing columns in +table+.
         
     | 
| 
       171 
259 
     | 
    
         
             
                  #
         
     | 
| 
       172 
     | 
    
         
            -
                  #  
     | 
| 
       173 
     | 
    
         
            -
                  # 
     | 
| 
       174 
     | 
    
         
            -
                  # 
     | 
| 
       175 
     | 
    
         
            -
                  # 
     | 
| 
       176 
     | 
    
         
            -
                  # 
     | 
| 
       177 
     | 
    
         
            -
                  # 
     | 
| 
      
 260 
     | 
    
         
            +
                  #   # change_table() yields a Table instance
         
     | 
| 
      
 261 
     | 
    
         
            +
                  #   change_table(:suppliers) do |t|
         
     | 
| 
      
 262 
     | 
    
         
            +
                  #     t.column :name, :string, limit: 60
         
     | 
| 
      
 263 
     | 
    
         
            +
                  #     # Other column alterations here
         
     | 
| 
      
 264 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 265 
     | 
    
         
            +
                  #
         
     | 
| 
      
 266 
     | 
    
         
            +
                  # The +options+ hash can include the following keys:
         
     | 
| 
      
 267 
     | 
    
         
            +
                  # [<tt>:bulk</tt>]
         
     | 
| 
      
 268 
     | 
    
         
            +
                  #   Set this to true to make this a bulk alter query, such as
         
     | 
| 
      
 269 
     | 
    
         
            +
                  #
         
     | 
| 
      
 270 
     | 
    
         
            +
                  #     ALTER TABLE `users` ADD COLUMN age INT(11), ADD COLUMN birthdate DATETIME ...
         
     | 
| 
      
 271 
     | 
    
         
            +
                  #
         
     | 
| 
      
 272 
     | 
    
         
            +
                  #   Defaults to false.
         
     | 
| 
       178 
273 
     | 
    
         
             
                  #
         
     | 
| 
       179 
     | 
    
         
            -
                  # ===== Examples
         
     | 
| 
       180 
274 
     | 
    
         
             
                  # ====== Add a column
         
     | 
| 
       181 
     | 
    
         
            -
                  # 
     | 
| 
       182 
     | 
    
         
            -
                  # 
     | 
| 
       183 
     | 
    
         
            -
                  # 
     | 
| 
      
 275 
     | 
    
         
            +
                  #
         
     | 
| 
      
 276 
     | 
    
         
            +
                  #   change_table(:suppliers) do |t|
         
     | 
| 
      
 277 
     | 
    
         
            +
                  #     t.column :name, :string, limit: 60
         
     | 
| 
      
 278 
     | 
    
         
            +
                  #   end
         
     | 
| 
       184 
279 
     | 
    
         
             
                  #
         
     | 
| 
       185 
280 
     | 
    
         
             
                  # ====== Add 2 integer columns
         
     | 
| 
       186 
     | 
    
         
            -
                  # 
     | 
| 
       187 
     | 
    
         
            -
                  # 
     | 
| 
       188 
     | 
    
         
            -
                  # 
     | 
| 
      
 281 
     | 
    
         
            +
                  #
         
     | 
| 
      
 282 
     | 
    
         
            +
                  #   change_table(:suppliers) do |t|
         
     | 
| 
      
 283 
     | 
    
         
            +
                  #     t.integer :width, :height, null: false, default: 0
         
     | 
| 
      
 284 
     | 
    
         
            +
                  #   end
         
     | 
| 
       189 
285 
     | 
    
         
             
                  #
         
     | 
| 
       190 
286 
     | 
    
         
             
                  # ====== Add created_at/updated_at columns
         
     | 
| 
       191 
     | 
    
         
            -
                  # 
     | 
| 
       192 
     | 
    
         
            -
                  # 
     | 
| 
       193 
     | 
    
         
            -
                  # 
     | 
| 
      
 287 
     | 
    
         
            +
                  #
         
     | 
| 
      
 288 
     | 
    
         
            +
                  #   change_table(:suppliers) do |t|
         
     | 
| 
      
 289 
     | 
    
         
            +
                  #     t.timestamps
         
     | 
| 
      
 290 
     | 
    
         
            +
                  #   end
         
     | 
| 
       194 
291 
     | 
    
         
             
                  #
         
     | 
| 
       195 
292 
     | 
    
         
             
                  # ====== Add a foreign key column
         
     | 
| 
       196 
     | 
    
         
            -
                  #  change_table(:suppliers) do |t|
         
     | 
| 
       197 
     | 
    
         
            -
                  #    t.references :company
         
     | 
| 
       198 
     | 
    
         
            -
                  #  end
         
     | 
| 
       199 
293 
     | 
    
         
             
                  #
         
     | 
| 
       200 
     | 
    
         
            -
                  # 
     | 
| 
      
 294 
     | 
    
         
            +
                  #   change_table(:suppliers) do |t|
         
     | 
| 
      
 295 
     | 
    
         
            +
                  #     t.references :company
         
     | 
| 
      
 296 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 297 
     | 
    
         
            +
                  #
         
     | 
| 
      
 298 
     | 
    
         
            +
                  # Creates a <tt>company_id(integer)</tt> column.
         
     | 
| 
       201 
299 
     | 
    
         
             
                  #
         
     | 
| 
       202 
300 
     | 
    
         
             
                  # ====== Add a polymorphic foreign key column
         
     | 
| 
      
 301 
     | 
    
         
            +
                  #
         
     | 
| 
       203 
302 
     | 
    
         
             
                  #  change_table(:suppliers) do |t|
         
     | 
| 
       204 
     | 
    
         
            -
                  #    t.belongs_to :company, : 
     | 
| 
      
 303 
     | 
    
         
            +
                  #    t.belongs_to :company, polymorphic: true
         
     | 
| 
       205 
304 
     | 
    
         
             
                  #  end
         
     | 
| 
       206 
305 
     | 
    
         
             
                  #
         
     | 
| 
       207 
     | 
    
         
            -
                  # Creates <tt>company_type(varchar)</tt> and <tt>company_id(integer)</tt> columns
         
     | 
| 
      
 306 
     | 
    
         
            +
                  # Creates <tt>company_type(varchar)</tt> and <tt>company_id(integer)</tt> columns.
         
     | 
| 
       208 
307 
     | 
    
         
             
                  #
         
     | 
| 
       209 
308 
     | 
    
         
             
                  # ====== Remove a column
         
     | 
| 
      
 309 
     | 
    
         
            +
                  #
         
     | 
| 
       210 
310 
     | 
    
         
             
                  #  change_table(:suppliers) do |t|
         
     | 
| 
       211 
311 
     | 
    
         
             
                  #    t.remove :company
         
     | 
| 
       212 
312 
     | 
    
         
             
                  #  end
         
     | 
| 
       213 
313 
     | 
    
         
             
                  #
         
     | 
| 
       214 
314 
     | 
    
         
             
                  # ====== Remove several columns
         
     | 
| 
      
 315 
     | 
    
         
            +
                  #
         
     | 
| 
       215 
316 
     | 
    
         
             
                  #  change_table(:suppliers) do |t|
         
     | 
| 
       216 
317 
     | 
    
         
             
                  #    t.remove :company_id
         
     | 
| 
       217 
318 
     | 
    
         
             
                  #    t.remove :width, :height
         
     | 
| 
       218 
319 
     | 
    
         
             
                  #  end
         
     | 
| 
       219 
320 
     | 
    
         
             
                  #
         
     | 
| 
       220 
321 
     | 
    
         
             
                  # ====== Remove an index
         
     | 
| 
      
 322 
     | 
    
         
            +
                  #
         
     | 
| 
       221 
323 
     | 
    
         
             
                  #  change_table(:suppliers) do |t|
         
     | 
| 
       222 
324 
     | 
    
         
             
                  #    t.remove_index :company_id
         
     | 
| 
       223 
325 
     | 
    
         
             
                  #  end
         
     | 
| 
       224 
326 
     | 
    
         
             
                  #
         
     | 
| 
       225 
     | 
    
         
            -
                  # See also Table for details on
         
     | 
| 
       226 
     | 
    
         
            -
                   
     | 
| 
       227 
     | 
    
         
            -
             
     | 
| 
       228 
     | 
    
         
            -
             
     | 
| 
      
 327 
     | 
    
         
            +
                  # See also Table for details on all of the various column transformation.
         
     | 
| 
      
 328 
     | 
    
         
            +
                  def change_table(table_name, options = {})
         
     | 
| 
      
 329 
     | 
    
         
            +
                    if supports_bulk_alter? && options[:bulk]
         
     | 
| 
      
 330 
     | 
    
         
            +
                      recorder = ActiveRecord::Migration::CommandRecorder.new(self)
         
     | 
| 
      
 331 
     | 
    
         
            +
                      yield update_table_definition(table_name, recorder)
         
     | 
| 
      
 332 
     | 
    
         
            +
                      bulk_change_table(table_name, recorder.commands)
         
     | 
| 
      
 333 
     | 
    
         
            +
                    else
         
     | 
| 
      
 334 
     | 
    
         
            +
                      yield update_table_definition(table_name, self)
         
     | 
| 
      
 335 
     | 
    
         
            +
                    end
         
     | 
| 
       229 
336 
     | 
    
         
             
                  end
         
     | 
| 
       230 
337 
     | 
    
         | 
| 
       231 
338 
     | 
    
         
             
                  # Renames a table.
         
     | 
| 
       232 
     | 
    
         
            -
                  # 
     | 
| 
       233 
     | 
    
         
            -
                  # 
     | 
| 
      
 339 
     | 
    
         
            +
                  #
         
     | 
| 
      
 340 
     | 
    
         
            +
                  #   rename_table('octopuses', 'octopi')
         
     | 
| 
      
 341 
     | 
    
         
            +
                  #
         
     | 
| 
       234 
342 
     | 
    
         
             
                  def rename_table(table_name, new_name)
         
     | 
| 
       235 
343 
     | 
    
         
             
                    raise NotImplementedError, "rename_table is not implemented"
         
     | 
| 
       236 
344 
     | 
    
         
             
                  end
         
     | 
| 
       237 
345 
     | 
    
         | 
| 
       238 
346 
     | 
    
         
             
                  # Drops a table from the database.
         
     | 
| 
      
 347 
     | 
    
         
            +
                  #
         
     | 
| 
      
 348 
     | 
    
         
            +
                  # Although this command ignores +options+ and the block if one is given, it can be helpful
         
     | 
| 
      
 349 
     | 
    
         
            +
                  # to provide these in a migration's +change+ method so it can be reverted.
         
     | 
| 
      
 350 
     | 
    
         
            +
                  # In that case, +options+ and the block will be used by create_table.
         
     | 
| 
       239 
351 
     | 
    
         
             
                  def drop_table(table_name, options = {})
         
     | 
| 
       240 
352 
     | 
    
         
             
                    execute "DROP TABLE #{quote_table_name(table_name)}"
         
     | 
| 
       241 
353 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -243,142 +355,205 @@ module ActiveRecord 
     | 
|
| 
       243 
355 
     | 
    
         
             
                  # Adds a new column to the named table.
         
     | 
| 
       244 
356 
     | 
    
         
             
                  # See TableDefinition#column for details of the options you can use.
         
     | 
| 
       245 
357 
     | 
    
         
             
                  def add_column(table_name, column_name, type, options = {})
         
     | 
| 
       246 
     | 
    
         
            -
                     
     | 
| 
       247 
     | 
    
         
            -
                     
     | 
| 
       248 
     | 
    
         
            -
                    execute 
     | 
| 
       249 
     | 
    
         
            -
                  end
         
     | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
       251 
     | 
    
         
            -
                  # Removes the  
     | 
| 
       252 
     | 
    
         
            -
                  # 
     | 
| 
       253 
     | 
    
         
            -
                  # 
     | 
| 
       254 
     | 
    
         
            -
                  # 
     | 
| 
       255 
     | 
    
         
            -
                  def  
     | 
| 
       256 
     | 
    
         
            -
                    raise ArgumentError.new("You must specify at least one column name. 
     | 
| 
       257 
     | 
    
         
            -
                    column_names. 
     | 
| 
       258 
     | 
    
         
            -
                       
     | 
| 
      
 358 
     | 
    
         
            +
                    at = create_alter_table table_name
         
     | 
| 
      
 359 
     | 
    
         
            +
                    at.add_column(column_name, type, options)
         
     | 
| 
      
 360 
     | 
    
         
            +
                    execute schema_creation.accept at
         
     | 
| 
      
 361 
     | 
    
         
            +
                  end
         
     | 
| 
      
 362 
     | 
    
         
            +
             
     | 
| 
      
 363 
     | 
    
         
            +
                  # Removes the given columns from the table definition.
         
     | 
| 
      
 364 
     | 
    
         
            +
                  #
         
     | 
| 
      
 365 
     | 
    
         
            +
                  #   remove_columns(:suppliers, :qualification, :experience)
         
     | 
| 
      
 366 
     | 
    
         
            +
                  #
         
     | 
| 
      
 367 
     | 
    
         
            +
                  def remove_columns(table_name, *column_names)
         
     | 
| 
      
 368 
     | 
    
         
            +
                    raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)") if column_names.empty?
         
     | 
| 
      
 369 
     | 
    
         
            +
                    column_names.each do |column_name|
         
     | 
| 
      
 370 
     | 
    
         
            +
                      remove_column(table_name, column_name)
         
     | 
| 
       259 
371 
     | 
    
         
             
                    end
         
     | 
| 
       260 
372 
     | 
    
         
             
                  end
         
     | 
| 
       261 
     | 
    
         
            -
             
     | 
| 
      
 373 
     | 
    
         
            +
             
     | 
| 
      
 374 
     | 
    
         
            +
                  # Removes the column from the table definition.
         
     | 
| 
      
 375 
     | 
    
         
            +
                  #
         
     | 
| 
      
 376 
     | 
    
         
            +
                  #   remove_column(:suppliers, :qualification)
         
     | 
| 
      
 377 
     | 
    
         
            +
                  #
         
     | 
| 
      
 378 
     | 
    
         
            +
                  # The +type+ and +options+ parameters will be ignored if present. It can be helpful
         
     | 
| 
      
 379 
     | 
    
         
            +
                  # to provide these in a migration's +change+ method so it can be reverted.
         
     | 
| 
      
 380 
     | 
    
         
            +
                  # In that case, +type+ and +options+ will be used by add_column.
         
     | 
| 
      
 381 
     | 
    
         
            +
                  def remove_column(table_name, column_name, type = nil, options = {})
         
     | 
| 
      
 382 
     | 
    
         
            +
                    execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
         
     | 
| 
      
 383 
     | 
    
         
            +
                  end
         
     | 
| 
       262 
384 
     | 
    
         | 
| 
       263 
385 
     | 
    
         
             
                  # Changes the column's definition according to the new options.
         
     | 
| 
       264 
386 
     | 
    
         
             
                  # See TableDefinition#column for details of the options you can use.
         
     | 
| 
       265 
     | 
    
         
            -
                  # 
     | 
| 
       266 
     | 
    
         
            -
                  # 
     | 
| 
       267 
     | 
    
         
            -
                  # 
     | 
| 
      
 387 
     | 
    
         
            +
                  #
         
     | 
| 
      
 388 
     | 
    
         
            +
                  #   change_column(:suppliers, :name, :string, limit: 80)
         
     | 
| 
      
 389 
     | 
    
         
            +
                  #   change_column(:accounts, :description, :text)
         
     | 
| 
      
 390 
     | 
    
         
            +
                  #
         
     | 
| 
       268 
391 
     | 
    
         
             
                  def change_column(table_name, column_name, type, options = {})
         
     | 
| 
       269 
392 
     | 
    
         
             
                    raise NotImplementedError, "change_column is not implemented"
         
     | 
| 
       270 
393 
     | 
    
         
             
                  end
         
     | 
| 
       271 
394 
     | 
    
         | 
| 
       272 
     | 
    
         
            -
                  # Sets a new default value for a column 
     | 
| 
       273 
     | 
    
         
            -
                  # 
     | 
| 
       274 
     | 
    
         
            -
                  #  
     | 
| 
       275 
     | 
    
         
            -
                  #  
     | 
| 
       276 
     | 
    
         
            -
                  # 
     | 
| 
       277 
     | 
    
         
            -
                  # 
     | 
| 
      
 395 
     | 
    
         
            +
                  # Sets a new default value for a column:
         
     | 
| 
      
 396 
     | 
    
         
            +
                  #
         
     | 
| 
      
 397 
     | 
    
         
            +
                  #   change_column_default(:suppliers, :qualification, 'new')
         
     | 
| 
      
 398 
     | 
    
         
            +
                  #   change_column_default(:accounts, :authorized, 1)
         
     | 
| 
      
 399 
     | 
    
         
            +
                  #
         
     | 
| 
      
 400 
     | 
    
         
            +
                  # Setting the default to +nil+ effectively drops the default:
         
     | 
| 
      
 401 
     | 
    
         
            +
                  #
         
     | 
| 
      
 402 
     | 
    
         
            +
                  #   change_column_default(:users, :email, nil)
         
     | 
| 
      
 403 
     | 
    
         
            +
                  #
         
     | 
| 
       278 
404 
     | 
    
         
             
                  def change_column_default(table_name, column_name, default)
         
     | 
| 
       279 
405 
     | 
    
         
             
                    raise NotImplementedError, "change_column_default is not implemented"
         
     | 
| 
       280 
406 
     | 
    
         
             
                  end
         
     | 
| 
       281 
407 
     | 
    
         | 
| 
      
 408 
     | 
    
         
            +
                  # Sets or removes a +NOT NULL+ constraint on a column. The +null+ flag
         
     | 
| 
      
 409 
     | 
    
         
            +
                  # indicates whether the value can be +NULL+. For example
         
     | 
| 
      
 410 
     | 
    
         
            +
                  #
         
     | 
| 
      
 411 
     | 
    
         
            +
                  #   change_column_null(:users, :nickname, false)
         
     | 
| 
      
 412 
     | 
    
         
            +
                  #
         
     | 
| 
      
 413 
     | 
    
         
            +
                  # says nicknames cannot be +NULL+ (adds the constraint), whereas
         
     | 
| 
      
 414 
     | 
    
         
            +
                  #
         
     | 
| 
      
 415 
     | 
    
         
            +
                  #   change_column_null(:users, :nickname, true)
         
     | 
| 
      
 416 
     | 
    
         
            +
                  #
         
     | 
| 
      
 417 
     | 
    
         
            +
                  # allows them to be +NULL+ (drops the constraint).
         
     | 
| 
      
 418 
     | 
    
         
            +
                  #
         
     | 
| 
      
 419 
     | 
    
         
            +
                  # The method accepts an optional fourth argument to replace existing
         
     | 
| 
      
 420 
     | 
    
         
            +
                  # +NULL+s with some other value. Use that one when enabling the
         
     | 
| 
      
 421 
     | 
    
         
            +
                  # constraint if needed, since otherwise those rows would not be valid.
         
     | 
| 
      
 422 
     | 
    
         
            +
                  #
         
     | 
| 
      
 423 
     | 
    
         
            +
                  # Please note the fourth argument does not set a column's default.
         
     | 
| 
      
 424 
     | 
    
         
            +
                  def change_column_null(table_name, column_name, null, default = nil)
         
     | 
| 
      
 425 
     | 
    
         
            +
                    raise NotImplementedError, "change_column_null is not implemented"
         
     | 
| 
      
 426 
     | 
    
         
            +
                  end
         
     | 
| 
      
 427 
     | 
    
         
            +
             
     | 
| 
       282 
428 
     | 
    
         
             
                  # Renames a column.
         
     | 
| 
       283 
     | 
    
         
            -
                  # 
     | 
| 
       284 
     | 
    
         
            -
                  # 
     | 
| 
      
 429 
     | 
    
         
            +
                  #
         
     | 
| 
      
 430 
     | 
    
         
            +
                  #   rename_column(:suppliers, :description, :name)
         
     | 
| 
      
 431 
     | 
    
         
            +
                  #
         
     | 
| 
       285 
432 
     | 
    
         
             
                  def rename_column(table_name, column_name, new_column_name)
         
     | 
| 
       286 
433 
     | 
    
         
             
                    raise NotImplementedError, "rename_column is not implemented"
         
     | 
| 
       287 
434 
     | 
    
         
             
                  end
         
     | 
| 
       288 
435 
     | 
    
         | 
| 
       289 
     | 
    
         
            -
                  # Adds a new index to the table. 
     | 
| 
      
 436 
     | 
    
         
            +
                  # Adds a new index to the table. +column_name+ can be a single Symbol, or
         
     | 
| 
       290 
437 
     | 
    
         
             
                  # an Array of Symbols.
         
     | 
| 
       291 
438 
     | 
    
         
             
                  #
         
     | 
| 
       292 
     | 
    
         
            -
                  # The index will be named after the table and the  
     | 
| 
       293 
     | 
    
         
            -
                  #  
     | 
| 
      
 439 
     | 
    
         
            +
                  # The index will be named after the table and the column name(s), unless
         
     | 
| 
      
 440 
     | 
    
         
            +
                  # you pass <tt>:name</tt> as an option.
         
     | 
| 
       294 
441 
     | 
    
         
             
                  #
         
     | 
| 
       295 
     | 
    
         
            -
                  #  
     | 
| 
       296 
     | 
    
         
            -
                  # for the index. For example, when you specify an index on two columns
         
     | 
| 
       297 
     | 
    
         
            -
                  # [<tt>:first</tt>, <tt>:last</tt>], the DBMS creates an index for both columns as well as an
         
     | 
| 
       298 
     | 
    
         
            -
                  # index for the first column <tt>:first</tt>. Using just the first name for this index
         
     | 
| 
       299 
     | 
    
         
            -
                  # makes sense, because you will never have to create a singular index with this
         
     | 
| 
       300 
     | 
    
         
            -
                  # name.
         
     | 
| 
      
 442 
     | 
    
         
            +
                  # ====== Creating a simple index
         
     | 
| 
       301 
443 
     | 
    
         
             
                  #
         
     | 
| 
       302 
     | 
    
         
            -
                  #  
     | 
| 
      
 444 
     | 
    
         
            +
                  #   add_index(:suppliers, :name)
         
     | 
| 
       303 
445 
     | 
    
         
             
                  #
         
     | 
| 
       304 
     | 
    
         
            -
                  #  
     | 
| 
       305 
     | 
    
         
            -
                  # 
     | 
| 
       306 
     | 
    
         
            -
                  #  
     | 
| 
       307 
     | 
    
         
            -
                  #  CREATE INDEX suppliers_name_index ON suppliers(name)
         
     | 
| 
      
 446 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 447 
     | 
    
         
            +
                  #
         
     | 
| 
      
 448 
     | 
    
         
            +
                  #   CREATE INDEX suppliers_name_index ON suppliers(name)
         
     | 
| 
       308 
449 
     | 
    
         
             
                  #
         
     | 
| 
       309 
450 
     | 
    
         
             
                  # ====== Creating a unique index
         
     | 
| 
       310 
     | 
    
         
            -
                  # 
     | 
| 
       311 
     | 
    
         
            -
                  #  
     | 
| 
       312 
     | 
    
         
            -
                  # 
     | 
| 
      
 451 
     | 
    
         
            +
                  #
         
     | 
| 
      
 452 
     | 
    
         
            +
                  #   add_index(:accounts, [:branch_id, :party_id], unique: true)
         
     | 
| 
      
 453 
     | 
    
         
            +
                  #
         
     | 
| 
      
 454 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 455 
     | 
    
         
            +
                  #
         
     | 
| 
      
 456 
     | 
    
         
            +
                  #   CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
         
     | 
| 
       313 
457 
     | 
    
         
             
                  #
         
     | 
| 
       314 
458 
     | 
    
         
             
                  # ====== Creating a named index
         
     | 
| 
       315 
     | 
    
         
            -
                  # 
     | 
| 
       316 
     | 
    
         
            -
                  #  
     | 
| 
      
 459 
     | 
    
         
            +
                  #
         
     | 
| 
      
 460 
     | 
    
         
            +
                  #   add_index(:accounts, [:branch_id, :party_id], unique: true, name: 'by_branch_party')
         
     | 
| 
      
 461 
     | 
    
         
            +
                  #
         
     | 
| 
      
 462 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 463 
     | 
    
         
            +
                  #
         
     | 
| 
       317 
464 
     | 
    
         
             
                  #  CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
         
     | 
| 
       318 
465 
     | 
    
         
             
                  #
         
     | 
| 
       319 
466 
     | 
    
         
             
                  # ====== Creating an index with specific key length
         
     | 
| 
       320 
     | 
    
         
            -
                  #  add_index(:accounts, :name, :name => 'by_name', :length => 10)
         
     | 
| 
       321 
     | 
    
         
            -
                  # generates
         
     | 
| 
       322 
     | 
    
         
            -
                  #  CREATE INDEX by_name ON accounts(name(10))
         
     | 
| 
       323 
467 
     | 
    
         
             
                  #
         
     | 
| 
       324 
     | 
    
         
            -
                  # 
     | 
| 
       325 
     | 
    
         
            -
                  # 
     | 
| 
       326 
     | 
    
         
            -
                  # 
     | 
| 
      
 468 
     | 
    
         
            +
                  #   add_index(:accounts, :name, name: 'by_name', length: 10)
         
     | 
| 
      
 469 
     | 
    
         
            +
                  #
         
     | 
| 
      
 470 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 471 
     | 
    
         
            +
                  #
         
     | 
| 
      
 472 
     | 
    
         
            +
                  #   CREATE INDEX by_name ON accounts(name(10))
         
     | 
| 
      
 473 
     | 
    
         
            +
                  #
         
     | 
| 
      
 474 
     | 
    
         
            +
                  #   add_index(:accounts, [:name, :surname], name: 'by_name_surname', length: {name: 10, surname: 15})
         
     | 
| 
      
 475 
     | 
    
         
            +
                  #
         
     | 
| 
      
 476 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 477 
     | 
    
         
            +
                  #
         
     | 
| 
      
 478 
     | 
    
         
            +
                  #   CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
         
     | 
| 
      
 479 
     | 
    
         
            +
                  #
         
     | 
| 
      
 480 
     | 
    
         
            +
                  # Note: SQLite doesn't support index length.
         
     | 
| 
      
 481 
     | 
    
         
            +
                  #
         
     | 
| 
      
 482 
     | 
    
         
            +
                  # ====== Creating an index with a sort order (desc or asc, asc is the default)
         
     | 
| 
      
 483 
     | 
    
         
            +
                  #
         
     | 
| 
      
 484 
     | 
    
         
            +
                  #   add_index(:accounts, [:branch_id, :party_id, :surname], order: {branch_id: :desc, party_id: :asc})
         
     | 
| 
      
 485 
     | 
    
         
            +
                  #
         
     | 
| 
      
 486 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 487 
     | 
    
         
            +
                  #
         
     | 
| 
      
 488 
     | 
    
         
            +
                  #   CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
         
     | 
| 
      
 489 
     | 
    
         
            +
                  #
         
     | 
| 
      
 490 
     | 
    
         
            +
                  # Note: MySQL doesn't yet support index order (it accepts the syntax but ignores it).
         
     | 
| 
       327 
491 
     | 
    
         
             
                  #
         
     | 
| 
       328 
     | 
    
         
            -
                  #  
     | 
| 
      
 492 
     | 
    
         
            +
                  # ====== Creating a partial index
         
     | 
| 
      
 493 
     | 
    
         
            +
                  #
         
     | 
| 
      
 494 
     | 
    
         
            +
                  #   add_index(:accounts, [:branch_id, :party_id], unique: true, where: "active")
         
     | 
| 
      
 495 
     | 
    
         
            +
                  #
         
     | 
| 
      
 496 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 497 
     | 
    
         
            +
                  #
         
     | 
| 
      
 498 
     | 
    
         
            +
                  #   CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id) WHERE active
         
     | 
| 
      
 499 
     | 
    
         
            +
                  #
         
     | 
| 
      
 500 
     | 
    
         
            +
                  # ====== Creating an index with a specific method
         
     | 
| 
      
 501 
     | 
    
         
            +
                  #
         
     | 
| 
      
 502 
     | 
    
         
            +
                  #   add_index(:developers, :name, using: 'btree')
         
     | 
| 
      
 503 
     | 
    
         
            +
                  #
         
     | 
| 
      
 504 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 505 
     | 
    
         
            +
                  #
         
     | 
| 
      
 506 
     | 
    
         
            +
                  #   CREATE INDEX index_developers_on_name ON developers USING btree (name) -- PostgreSQL
         
     | 
| 
      
 507 
     | 
    
         
            +
                  #   CREATE INDEX index_developers_on_name USING btree ON developers (name) -- MySQL
         
     | 
| 
      
 508 
     | 
    
         
            +
                  #
         
     | 
| 
      
 509 
     | 
    
         
            +
                  # Note: only supported by PostgreSQL and MySQL
         
     | 
| 
      
 510 
     | 
    
         
            +
                  #
         
     | 
| 
      
 511 
     | 
    
         
            +
                  # ====== Creating an index with a specific type
         
     | 
| 
      
 512 
     | 
    
         
            +
                  #
         
     | 
| 
      
 513 
     | 
    
         
            +
                  #   add_index(:developers, :name, type: :fulltext)
         
     | 
| 
      
 514 
     | 
    
         
            +
                  #
         
     | 
| 
      
 515 
     | 
    
         
            +
                  # generates:
         
     | 
| 
      
 516 
     | 
    
         
            +
                  #
         
     | 
| 
      
 517 
     | 
    
         
            +
                  #   CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
         
     | 
| 
      
 518 
     | 
    
         
            +
                  #
         
     | 
| 
      
 519 
     | 
    
         
            +
                  # Note: only supported by MySQL. Supported: <tt>:fulltext</tt> and <tt>:spatial</tt> on MyISAM tables.
         
     | 
| 
       329 
520 
     | 
    
         
             
                  def add_index(table_name, column_name, options = {})
         
     | 
| 
       330 
     | 
    
         
            -
                     
     | 
| 
       331 
     | 
    
         
            -
             
     | 
| 
       332 
     | 
    
         
            -
                    column_names = Array.wrap(column_name)
         
     | 
| 
       333 
     | 
    
         
            -
                    index_name   = index_name(table_name, :column => column_names)
         
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
                    if Hash === options # legacy support, since this param was a string
         
     | 
| 
       336 
     | 
    
         
            -
                      index_type = options[:unique] ? "UNIQUE" : ""
         
     | 
| 
       337 
     | 
    
         
            -
                      index_name = options[:name] || index_name
         
     | 
| 
       338 
     | 
    
         
            -
                    else
         
     | 
| 
       339 
     | 
    
         
            -
                      index_type = options
         
     | 
| 
       340 
     | 
    
         
            -
                    end
         
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
       342 
     | 
    
         
            -
                    if index_name.length > index_name_length
         
     | 
| 
       343 
     | 
    
         
            -
                      @logger.warn("Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters. Skipping.")
         
     | 
| 
       344 
     | 
    
         
            -
                      return
         
     | 
| 
       345 
     | 
    
         
            -
                    end
         
     | 
| 
       346 
     | 
    
         
            -
                    if index_name_exists?(table_name, index_name, false)
         
     | 
| 
       347 
     | 
    
         
            -
                      @logger.warn("Index name '#{index_name}' on table '#{table_name}' already exists. Skipping.")
         
     | 
| 
       348 
     | 
    
         
            -
                      return
         
     | 
| 
       349 
     | 
    
         
            -
                    end
         
     | 
| 
       350 
     | 
    
         
            -
                    quoted_column_names = quoted_columns_for_index(column_names, options).join(", ")
         
     | 
| 
       351 
     | 
    
         
            -
             
     | 
| 
       352 
     | 
    
         
            -
                    execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
         
     | 
| 
      
 521 
     | 
    
         
            +
                    index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
         
     | 
| 
      
 522 
     | 
    
         
            +
                    execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
         
     | 
| 
       353 
523 
     | 
    
         
             
                  end
         
     | 
| 
       354 
524 
     | 
    
         | 
| 
       355 
     | 
    
         
            -
                  #  
     | 
| 
      
 525 
     | 
    
         
            +
                  # Removes the given index from the table.
         
     | 
| 
      
 526 
     | 
    
         
            +
                  #
         
     | 
| 
      
 527 
     | 
    
         
            +
                  # Removes the +index_accounts_on_column+ in the +accounts+ table.
         
     | 
| 
      
 528 
     | 
    
         
            +
                  #
         
     | 
| 
      
 529 
     | 
    
         
            +
                  #   remove_index :accounts, :column
         
     | 
| 
      
 530 
     | 
    
         
            +
                  #
         
     | 
| 
      
 531 
     | 
    
         
            +
                  # Removes the index named +index_accounts_on_branch_id+ in the +accounts+ table.
         
     | 
| 
      
 532 
     | 
    
         
            +
                  #
         
     | 
| 
      
 533 
     | 
    
         
            +
                  #   remove_index :accounts, column: :branch_id
         
     | 
| 
      
 534 
     | 
    
         
            +
                  #
         
     | 
| 
      
 535 
     | 
    
         
            +
                  # Removes the index named +index_accounts_on_branch_id_and_party_id+ in the +accounts+ table.
         
     | 
| 
      
 536 
     | 
    
         
            +
                  #
         
     | 
| 
      
 537 
     | 
    
         
            +
                  #   remove_index :accounts, column: [:branch_id, :party_id]
         
     | 
| 
      
 538 
     | 
    
         
            +
                  #
         
     | 
| 
      
 539 
     | 
    
         
            +
                  # Removes the index named +by_branch_party+ in the +accounts+ table.
         
     | 
| 
      
 540 
     | 
    
         
            +
                  #
         
     | 
| 
      
 541 
     | 
    
         
            +
                  #   remove_index :accounts, name: :by_branch_party
         
     | 
| 
       356 
542 
     | 
    
         
             
                  #
         
     | 
| 
       357 
     | 
    
         
            -
                  # Remove the suppliers_name_index in the suppliers table.
         
     | 
| 
       358 
     | 
    
         
            -
                  #   remove_index :suppliers, :name
         
     | 
| 
       359 
     | 
    
         
            -
                  # Remove the index named accounts_branch_id_index in the accounts table.
         
     | 
| 
       360 
     | 
    
         
            -
                  #   remove_index :accounts, :column => :branch_id
         
     | 
| 
       361 
     | 
    
         
            -
                  # Remove the index named accounts_branch_id_party_id_index in the accounts table.
         
     | 
| 
       362 
     | 
    
         
            -
                  #   remove_index :accounts, :column => [:branch_id, :party_id]
         
     | 
| 
       363 
     | 
    
         
            -
                  # Remove the index named by_branch_party in the accounts table.
         
     | 
| 
       364 
     | 
    
         
            -
                  #   remove_index :accounts, :name => :by_branch_party
         
     | 
| 
       365 
543 
     | 
    
         
             
                  def remove_index(table_name, options = {})
         
     | 
| 
       366 
     | 
    
         
            -
                     
     | 
| 
       367 
     | 
    
         
            -
                    unless index_name_exists?(table_name, index_name, true)
         
     | 
| 
       368 
     | 
    
         
            -
                      @logger.warn("Index name '#{index_name}' on table '#{table_name}' does not exist. Skipping.")
         
     | 
| 
       369 
     | 
    
         
            -
                      return
         
     | 
| 
       370 
     | 
    
         
            -
                    end
         
     | 
| 
       371 
     | 
    
         
            -
                    remove_index!(table_name, index_name)
         
     | 
| 
      
 544 
     | 
    
         
            +
                    remove_index!(table_name, index_name_for_remove(table_name, options))
         
     | 
| 
       372 
545 
     | 
    
         
             
                  end
         
     | 
| 
       373 
546 
     | 
    
         | 
| 
       374 
547 
     | 
    
         
             
                  def remove_index!(table_name, index_name) #:nodoc:
         
     | 
| 
       375 
548 
     | 
    
         
             
                    execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
         
     | 
| 
       376 
549 
     | 
    
         
             
                  end
         
     | 
| 
       377 
550 
     | 
    
         | 
| 
       378 
     | 
    
         
            -
                  #  
     | 
| 
      
 551 
     | 
    
         
            +
                  # Renames an index.
         
     | 
| 
      
 552 
     | 
    
         
            +
                  #
         
     | 
| 
      
 553 
     | 
    
         
            +
                  # Rename the +index_people_on_last_name+ index to +index_users_on_last_name+:
         
     | 
| 
       379 
554 
     | 
    
         
             
                  #
         
     | 
| 
       380 
     | 
    
         
            -
                  # Rename the index_people_on_last_name index to index_users_on_last_name
         
     | 
| 
       381 
555 
     | 
    
         
             
                  #   rename_index :people, 'index_people_on_last_name', 'index_users_on_last_name'
         
     | 
| 
      
 556 
     | 
    
         
            +
                  #
         
     | 
| 
       382 
557 
     | 
    
         
             
                  def rename_index(table_name, old_name, new_name)
         
     | 
| 
       383 
558 
     | 
    
         
             
                    # this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance)
         
     | 
| 
       384 
559 
     | 
    
         
             
                    old_index_def = indexes(table_name).detect { |i| i.name == old_name }
         
     | 
| 
         @@ -388,9 +563,9 @@ module ActiveRecord 
     | 
|
| 
       388 
563 
     | 
    
         
             
                  end
         
     | 
| 
       389 
564 
     | 
    
         | 
| 
       390 
565 
     | 
    
         
             
                  def index_name(table_name, options) #:nodoc:
         
     | 
| 
       391 
     | 
    
         
            -
                    if Hash === options 
     | 
| 
      
 566 
     | 
    
         
            +
                    if Hash === options
         
     | 
| 
       392 
567 
     | 
    
         
             
                      if options[:column]
         
     | 
| 
       393 
     | 
    
         
            -
                        "index_#{table_name}_on_#{Array 
     | 
| 
      
 568 
     | 
    
         
            +
                        "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
         
     | 
| 
       394 
569 
     | 
    
         
             
                      elsif options[:name]
         
     | 
| 
       395 
570 
     | 
    
         
             
                        options[:name]
         
     | 
| 
       396 
571 
     | 
    
         
             
                      else
         
     | 
| 
         @@ -401,57 +576,79 @@ module ActiveRecord 
     | 
|
| 
       401 
576 
     | 
    
         
             
                    end
         
     | 
| 
       402 
577 
     | 
    
         
             
                  end
         
     | 
| 
       403 
578 
     | 
    
         | 
| 
       404 
     | 
    
         
            -
                  #  
     | 
| 
      
 579 
     | 
    
         
            +
                  # Verifies the existence of an index with a given name.
         
     | 
| 
       405 
580 
     | 
    
         
             
                  #
         
     | 
| 
       406 
581 
     | 
    
         
             
                  # The default argument is returned if the underlying implementation does not define the indexes method,
         
     | 
| 
       407 
582 
     | 
    
         
             
                  # as there's no way to determine the correct answer in that case.
         
     | 
| 
       408 
583 
     | 
    
         
             
                  def index_name_exists?(table_name, index_name, default)
         
     | 
| 
       409 
584 
     | 
    
         
             
                    return default unless respond_to?(:indexes)
         
     | 
| 
      
 585 
     | 
    
         
            +
                    index_name = index_name.to_s
         
     | 
| 
       410 
586 
     | 
    
         
             
                    indexes(table_name).detect { |i| i.name == index_name }
         
     | 
| 
       411 
587 
     | 
    
         
             
                  end
         
     | 
| 
       412 
588 
     | 
    
         | 
| 
       413 
     | 
    
         
            -
                  #  
     | 
| 
       414 
     | 
    
         
            -
                  #  
     | 
| 
       415 
     | 
    
         
            -
                   
     | 
| 
      
 589 
     | 
    
         
            +
                  # Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
         
     | 
| 
      
 590 
     | 
    
         
            +
                  # <tt>add_reference</tt> and <tt>add_belongs_to</tt> are acceptable.
         
     | 
| 
      
 591 
     | 
    
         
            +
                  #
         
     | 
| 
      
 592 
     | 
    
         
            +
                  # ====== Create a user_id column
         
     | 
| 
      
 593 
     | 
    
         
            +
                  #
         
     | 
| 
      
 594 
     | 
    
         
            +
                  #   add_reference(:products, :user)
         
     | 
| 
      
 595 
     | 
    
         
            +
                  #
         
     | 
| 
      
 596 
     | 
    
         
            +
                  # ====== Create a supplier_id and supplier_type columns
         
     | 
| 
      
 597 
     | 
    
         
            +
                  #
         
     | 
| 
      
 598 
     | 
    
         
            +
                  #   add_belongs_to(:products, :supplier, polymorphic: true)
         
     | 
| 
      
 599 
     | 
    
         
            +
                  #
         
     | 
| 
      
 600 
     | 
    
         
            +
                  # ====== Create a supplier_id, supplier_type columns and appropriate index
         
     | 
| 
      
 601 
     | 
    
         
            +
                  #
         
     | 
| 
      
 602 
     | 
    
         
            +
                  #   add_reference(:products, :supplier, polymorphic: true, index: true)
         
     | 
| 
      
 603 
     | 
    
         
            +
                  #
         
     | 
| 
      
 604 
     | 
    
         
            +
                  def add_reference(table_name, ref_name, options = {})
         
     | 
| 
      
 605 
     | 
    
         
            +
                    polymorphic = options.delete(:polymorphic)
         
     | 
| 
      
 606 
     | 
    
         
            +
                    index_options = options.delete(:index)
         
     | 
| 
      
 607 
     | 
    
         
            +
                    add_column(table_name, "#{ref_name}_id", :integer, options)
         
     | 
| 
      
 608 
     | 
    
         
            +
                    add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
         
     | 
| 
      
 609 
     | 
    
         
            +
                    add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
         
     | 
| 
      
 610 
     | 
    
         
            +
                  end
         
     | 
| 
      
 611 
     | 
    
         
            +
                  alias :add_belongs_to :add_reference
         
     | 
| 
      
 612 
     | 
    
         
            +
             
     | 
| 
      
 613 
     | 
    
         
            +
                  # Removes the reference(s). Also removes a +type+ column if one exists.
         
     | 
| 
      
 614 
     | 
    
         
            +
                  # <tt>remove_reference</tt>, <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
         
     | 
| 
      
 615 
     | 
    
         
            +
                  #
         
     | 
| 
      
 616 
     | 
    
         
            +
                  # ====== Remove the reference
         
     | 
| 
      
 617 
     | 
    
         
            +
                  #
         
     | 
| 
      
 618 
     | 
    
         
            +
                  #   remove_reference(:products, :user, index: true)
         
     | 
| 
      
 619 
     | 
    
         
            +
                  #
         
     | 
| 
      
 620 
     | 
    
         
            +
                  # ====== Remove polymorphic reference
         
     | 
| 
      
 621 
     | 
    
         
            +
                  #
         
     | 
| 
      
 622 
     | 
    
         
            +
                  #   remove_reference(:products, :supplier, polymorphic: true)
         
     | 
| 
      
 623 
     | 
    
         
            +
                  #
         
     | 
| 
      
 624 
     | 
    
         
            +
                  def remove_reference(table_name, ref_name, options = {})
         
     | 
| 
      
 625 
     | 
    
         
            +
                    remove_column(table_name, "#{ref_name}_id")
         
     | 
| 
      
 626 
     | 
    
         
            +
                    remove_column(table_name, "#{ref_name}_type") if options[:polymorphic]
         
     | 
| 
       416 
627 
     | 
    
         
             
                  end
         
     | 
| 
      
 628 
     | 
    
         
            +
                  alias :remove_belongs_to :remove_reference
         
     | 
| 
       417 
629 
     | 
    
         | 
| 
       418 
630 
     | 
    
         
             
                  def dump_schema_information #:nodoc:
         
     | 
| 
       419 
631 
     | 
    
         
             
                    sm_table = ActiveRecord::Migrator.schema_migrations_table_name
         
     | 
| 
       420 
     | 
    
         
            -
             
     | 
| 
       421 
     | 
    
         
            -
                     
     | 
| 
      
 632 
     | 
    
         
            +
             
     | 
| 
      
 633 
     | 
    
         
            +
                    ActiveRecord::SchemaMigration.order('version').map { |sm|
         
     | 
| 
      
 634 
     | 
    
         
            +
                      "INSERT INTO #{sm_table} (version) VALUES ('#{sm.version}');"
         
     | 
| 
      
 635 
     | 
    
         
            +
                    }.join "\n\n"
         
     | 
| 
       422 
636 
     | 
    
         
             
                  end
         
     | 
| 
       423 
637 
     | 
    
         | 
| 
       424 
638 
     | 
    
         
             
                  # Should not be called normally, but this operation is non-destructive.
         
     | 
| 
       425 
639 
     | 
    
         
             
                  # The migrations module handles this automatically.
         
     | 
| 
       426 
640 
     | 
    
         
             
                  def initialize_schema_migrations_table
         
     | 
| 
       427 
     | 
    
         
            -
                     
     | 
| 
       428 
     | 
    
         
            -
             
     | 
| 
       429 
     | 
    
         
            -
                    unless table_exists?(sm_table)
         
     | 
| 
       430 
     | 
    
         
            -
                      create_table(sm_table, :id => false) do |schema_migrations_table|
         
     | 
| 
       431 
     | 
    
         
            -
                        schema_migrations_table.column :version, :string, :null => false
         
     | 
| 
       432 
     | 
    
         
            -
                      end
         
     | 
| 
       433 
     | 
    
         
            -
                      add_index sm_table, :version, :unique => true,
         
     | 
| 
       434 
     | 
    
         
            -
                        :name => "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
         
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
       436 
     | 
    
         
            -
                      # Backwards-compatibility: if we find schema_info, assume we've
         
     | 
| 
       437 
     | 
    
         
            -
                      # migrated up to that point:
         
     | 
| 
       438 
     | 
    
         
            -
                      si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
         
     | 
| 
       439 
     | 
    
         
            -
             
     | 
| 
       440 
     | 
    
         
            -
                      if table_exists?(si_table)
         
     | 
| 
       441 
     | 
    
         
            -
             
     | 
| 
       442 
     | 
    
         
            -
                        old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
         
     | 
| 
       443 
     | 
    
         
            -
                        assume_migrated_upto_version(old_version)
         
     | 
| 
       444 
     | 
    
         
            -
                        drop_table(si_table)
         
     | 
| 
       445 
     | 
    
         
            -
                      end
         
     | 
| 
       446 
     | 
    
         
            -
                    end
         
     | 
| 
      
 641 
     | 
    
         
            +
                    ActiveRecord::SchemaMigration.create_table
         
     | 
| 
       447 
642 
     | 
    
         
             
                  end
         
     | 
| 
       448 
643 
     | 
    
         | 
| 
       449 
     | 
    
         
            -
                  def assume_migrated_upto_version(version,  
     | 
| 
      
 644 
     | 
    
         
            +
                  def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migrator.migrations_paths)
         
     | 
| 
      
 645 
     | 
    
         
            +
                    migrations_paths = Array(migrations_paths)
         
     | 
| 
       450 
646 
     | 
    
         
             
                    version = version.to_i
         
     | 
| 
       451 
647 
     | 
    
         
             
                    sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
         
     | 
| 
       452 
648 
     | 
    
         | 
| 
       453 
649 
     | 
    
         
             
                    migrated = select_values("SELECT version FROM #{sm_table}").map { |v| v.to_i }
         
     | 
| 
       454 
     | 
    
         
            -
                     
     | 
| 
      
 650 
     | 
    
         
            +
                    paths = migrations_paths.map {|p| "#{p}/[0-9]*_*.rb" }
         
     | 
| 
      
 651 
     | 
    
         
            +
                    versions = Dir[*paths].map do |filename|
         
     | 
| 
       455 
652 
     | 
    
         
             
                      filename.split('/').last.split('_').first.to_i
         
     | 
| 
       456 
653 
     | 
    
         
             
                    end
         
     | 
| 
       457 
654 
     | 
    
         | 
| 
         @@ -471,7 +668,7 @@ module ActiveRecord 
     | 
|
| 
       471 
668 
     | 
    
         
             
                  end
         
     | 
| 
       472 
669 
     | 
    
         | 
| 
       473 
670 
     | 
    
         
             
                  def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
         
     | 
| 
       474 
     | 
    
         
            -
                    if native = native_database_types[type]
         
     | 
| 
      
 671 
     | 
    
         
            +
                    if native = native_database_types[type.to_sym]
         
     | 
| 
       475 
672 
     | 
    
         
             
                      column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
         
     | 
| 
       476 
673 
     | 
    
         | 
| 
       477 
674 
     | 
    
         
             
                      if type == :decimal # ignore limit, use precision and scale
         
     | 
| 
         @@ -484,7 +681,7 @@ module ActiveRecord 
     | 
|
| 
       484 
681 
     | 
    
         
             
                            column_type_sql << "(#{precision})"
         
     | 
| 
       485 
682 
     | 
    
         
             
                          end
         
     | 
| 
       486 
683 
     | 
    
         
             
                        elsif scale
         
     | 
| 
       487 
     | 
    
         
            -
                          raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale  
     | 
| 
      
 684 
     | 
    
         
            +
                          raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified"
         
     | 
| 
       488 
685 
     | 
    
         
             
                        end
         
     | 
| 
       489 
686 
     | 
    
         | 
| 
       490 
687 
     | 
    
         
             
                      elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
         
     | 
| 
         @@ -503,41 +700,174 @@ module ActiveRecord 
     | 
|
| 
       503 
700 
     | 
    
         
             
                    if options[:null] == false
         
     | 
| 
       504 
701 
     | 
    
         
             
                      sql << " NOT NULL"
         
     | 
| 
       505 
702 
     | 
    
         
             
                    end
         
     | 
| 
      
 703 
     | 
    
         
            +
                    if options[:auto_increment] == true
         
     | 
| 
      
 704 
     | 
    
         
            +
                      sql << " AUTO_INCREMENT"
         
     | 
| 
      
 705 
     | 
    
         
            +
                    end
         
     | 
| 
       506 
706 
     | 
    
         
             
                  end
         
     | 
| 
       507 
707 
     | 
    
         | 
| 
       508 
708 
     | 
    
         
             
                  # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
         
     | 
| 
       509 
709 
     | 
    
         
             
                  # Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax.
         
     | 
| 
       510 
710 
     | 
    
         
             
                  #
         
     | 
| 
       511 
711 
     | 
    
         
             
                  #   distinct("posts.id", "posts.created_at desc")
         
     | 
| 
      
 712 
     | 
    
         
            +
                  #
         
     | 
| 
       512 
713 
     | 
    
         
             
                  def distinct(columns, order_by)
         
     | 
| 
       513 
714 
     | 
    
         
             
                    "DISTINCT #{columns}"
         
     | 
| 
       514 
715 
     | 
    
         
             
                  end
         
     | 
| 
       515 
716 
     | 
    
         | 
| 
       516 
     | 
    
         
            -
                  # Adds timestamps (created_at and updated_at) columns to the named table.
         
     | 
| 
       517 
     | 
    
         
            -
                  # 
     | 
| 
       518 
     | 
    
         
            -
                  # 
     | 
| 
      
 717 
     | 
    
         
            +
                  # Adds timestamps (+created_at+ and +updated_at+) columns to the named table.
         
     | 
| 
      
 718 
     | 
    
         
            +
                  #
         
     | 
| 
      
 719 
     | 
    
         
            +
                  #   add_timestamps(:suppliers)
         
     | 
| 
      
 720 
     | 
    
         
            +
                  #
         
     | 
| 
       519 
721 
     | 
    
         
             
                  def add_timestamps(table_name)
         
     | 
| 
       520 
722 
     | 
    
         
             
                    add_column table_name, :created_at, :datetime
         
     | 
| 
       521 
723 
     | 
    
         
             
                    add_column table_name, :updated_at, :datetime
         
     | 
| 
       522 
724 
     | 
    
         
             
                  end
         
     | 
| 
       523 
725 
     | 
    
         | 
| 
       524 
     | 
    
         
            -
                  # Removes the timestamp columns (created_at and updated_at) from the table definition.
         
     | 
| 
       525 
     | 
    
         
            -
                  # 
     | 
| 
      
 726 
     | 
    
         
            +
                  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition.
         
     | 
| 
      
 727 
     | 
    
         
            +
                  #
         
     | 
| 
       526 
728 
     | 
    
         
             
                  #  remove_timestamps(:suppliers)
         
     | 
| 
      
 729 
     | 
    
         
            +
                  #
         
     | 
| 
       527 
730 
     | 
    
         
             
                  def remove_timestamps(table_name)
         
     | 
| 
       528 
731 
     | 
    
         
             
                    remove_column table_name, :updated_at
         
     | 
| 
       529 
732 
     | 
    
         
             
                    remove_column table_name, :created_at
         
     | 
| 
       530 
733 
     | 
    
         
             
                  end
         
     | 
| 
       531 
734 
     | 
    
         | 
| 
       532 
735 
     | 
    
         
             
                  protected
         
     | 
| 
      
 736 
     | 
    
         
            +
                    def add_index_sort_order(option_strings, column_names, options = {})
         
     | 
| 
      
 737 
     | 
    
         
            +
                      if options.is_a?(Hash) && order = options[:order]
         
     | 
| 
      
 738 
     | 
    
         
            +
                        case order
         
     | 
| 
      
 739 
     | 
    
         
            +
                        when Hash
         
     | 
| 
      
 740 
     | 
    
         
            +
                          column_names.each {|name| option_strings[name] += " #{order[name].upcase}" if order.has_key?(name)}
         
     | 
| 
      
 741 
     | 
    
         
            +
                        when String
         
     | 
| 
      
 742 
     | 
    
         
            +
                          column_names.each {|name| option_strings[name] += " #{order.upcase}"}
         
     | 
| 
      
 743 
     | 
    
         
            +
                        end
         
     | 
| 
      
 744 
     | 
    
         
            +
                      end
         
     | 
| 
      
 745 
     | 
    
         
            +
             
     | 
| 
      
 746 
     | 
    
         
            +
                      return option_strings
         
     | 
| 
      
 747 
     | 
    
         
            +
                    end
         
     | 
| 
      
 748 
     | 
    
         
            +
             
     | 
| 
       533 
749 
     | 
    
         
             
                    # Overridden by the mysql adapter for supporting index lengths
         
     | 
| 
       534 
750 
     | 
    
         
             
                    def quoted_columns_for_index(column_names, options = {})
         
     | 
| 
       535 
     | 
    
         
            -
                      column_names.map {|name|  
     | 
| 
      
 751 
     | 
    
         
            +
                      option_strings = Hash[column_names.map {|name| [name, '']}]
         
     | 
| 
      
 752 
     | 
    
         
            +
             
     | 
| 
      
 753 
     | 
    
         
            +
                      # add index sort order if supported
         
     | 
| 
      
 754 
     | 
    
         
            +
                      if supports_index_sort_order?
         
     | 
| 
      
 755 
     | 
    
         
            +
                        option_strings = add_index_sort_order(option_strings, column_names, options)
         
     | 
| 
      
 756 
     | 
    
         
            +
                      end
         
     | 
| 
      
 757 
     | 
    
         
            +
             
     | 
| 
      
 758 
     | 
    
         
            +
                      column_names.map {|name| quote_column_name(name) + option_strings[name]}
         
     | 
| 
       536 
759 
     | 
    
         
             
                    end
         
     | 
| 
       537 
760 
     | 
    
         | 
| 
       538 
761 
     | 
    
         
             
                    def options_include_default?(options)
         
     | 
| 
       539 
762 
     | 
    
         
             
                      options.include?(:default) && !(options[:null] == false && options[:default].nil?)
         
     | 
| 
       540 
763 
     | 
    
         
             
                    end
         
     | 
| 
      
 764 
     | 
    
         
            +
             
     | 
| 
      
 765 
     | 
    
         
            +
                    def add_index_options(table_name, column_name, options = {})
         
     | 
| 
      
 766 
     | 
    
         
            +
                      column_names = Array(column_name)
         
     | 
| 
      
 767 
     | 
    
         
            +
                      index_name   = index_name(table_name, column: column_names)
         
     | 
| 
      
 768 
     | 
    
         
            +
             
     | 
| 
      
 769 
     | 
    
         
            +
                      if Hash === options # legacy support, since this param was a string
         
     | 
| 
      
 770 
     | 
    
         
            +
                        options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
         
     | 
| 
      
 771 
     | 
    
         
            +
             
     | 
| 
      
 772 
     | 
    
         
            +
                        index_type = options[:unique] ? "UNIQUE" : ""
         
     | 
| 
      
 773 
     | 
    
         
            +
                        index_type = options[:type].to_s if options.key?(:type)
         
     | 
| 
      
 774 
     | 
    
         
            +
                        index_name = options[:name].to_s if options.key?(:name)
         
     | 
| 
      
 775 
     | 
    
         
            +
                        max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
         
     | 
| 
      
 776 
     | 
    
         
            +
             
     | 
| 
      
 777 
     | 
    
         
            +
                        if options.key?(:algorithm)
         
     | 
| 
      
 778 
     | 
    
         
            +
                          algorithm = index_algorithms.fetch(options[:algorithm]) {
         
     | 
| 
      
 779 
     | 
    
         
            +
                            raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}")
         
     | 
| 
      
 780 
     | 
    
         
            +
                          }
         
     | 
| 
      
 781 
     | 
    
         
            +
                        end
         
     | 
| 
      
 782 
     | 
    
         
            +
             
     | 
| 
      
 783 
     | 
    
         
            +
                        using = "USING #{options[:using]}" if options[:using].present?
         
     | 
| 
      
 784 
     | 
    
         
            +
             
     | 
| 
      
 785 
     | 
    
         
            +
                        if supports_partial_index?
         
     | 
| 
      
 786 
     | 
    
         
            +
                          index_options = options[:where] ? " WHERE #{options[:where]}" : ""
         
     | 
| 
      
 787 
     | 
    
         
            +
                        end
         
     | 
| 
      
 788 
     | 
    
         
            +
                      else
         
     | 
| 
      
 789 
     | 
    
         
            +
                        if options
         
     | 
| 
      
 790 
     | 
    
         
            +
                          message = "Passing a string as third argument of `add_index` is deprecated and will" +
         
     | 
| 
      
 791 
     | 
    
         
            +
                            " be removed in Rails 4.1." +
         
     | 
| 
      
 792 
     | 
    
         
            +
                            " Use add_index(#{table_name.inspect}, #{column_name.inspect}, unique: true) instead"
         
     | 
| 
      
 793 
     | 
    
         
            +
             
     | 
| 
      
 794 
     | 
    
         
            +
                          ActiveSupport::Deprecation.warn message
         
     | 
| 
      
 795 
     | 
    
         
            +
                        end
         
     | 
| 
      
 796 
     | 
    
         
            +
             
     | 
| 
      
 797 
     | 
    
         
            +
                        index_type = options
         
     | 
| 
      
 798 
     | 
    
         
            +
                        max_index_length = allowed_index_name_length
         
     | 
| 
      
 799 
     | 
    
         
            +
                        algorithm = using = nil
         
     | 
| 
      
 800 
     | 
    
         
            +
                      end
         
     | 
| 
      
 801 
     | 
    
         
            +
             
     | 
| 
      
 802 
     | 
    
         
            +
                      if index_name.length > max_index_length
         
     | 
| 
      
 803 
     | 
    
         
            +
                        raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters"
         
     | 
| 
      
 804 
     | 
    
         
            +
                      end
         
     | 
| 
      
 805 
     | 
    
         
            +
                      if index_name_exists?(table_name, index_name, false)
         
     | 
| 
      
 806 
     | 
    
         
            +
                        raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
         
     | 
| 
      
 807 
     | 
    
         
            +
                      end
         
     | 
| 
      
 808 
     | 
    
         
            +
                      index_columns = quoted_columns_for_index(column_names, options).join(", ")
         
     | 
| 
      
 809 
     | 
    
         
            +
             
     | 
| 
      
 810 
     | 
    
         
            +
                      [index_name, index_type, index_columns, index_options, algorithm, using]
         
     | 
| 
      
 811 
     | 
    
         
            +
                    end
         
     | 
| 
      
 812 
     | 
    
         
            +
             
     | 
| 
      
 813 
     | 
    
         
            +
                    def index_name_for_remove(table_name, options = {})
         
     | 
| 
      
 814 
     | 
    
         
            +
                      index_name = index_name(table_name, options)
         
     | 
| 
      
 815 
     | 
    
         
            +
             
     | 
| 
      
 816 
     | 
    
         
            +
                      unless index_name_exists?(table_name, index_name, true)
         
     | 
| 
      
 817 
     | 
    
         
            +
                        if options.is_a?(Hash) && options.has_key?(:name)
         
     | 
| 
      
 818 
     | 
    
         
            +
                          options_without_column = options.dup
         
     | 
| 
      
 819 
     | 
    
         
            +
                          options_without_column.delete :column
         
     | 
| 
      
 820 
     | 
    
         
            +
                          index_name_without_column = index_name(table_name, options_without_column)
         
     | 
| 
      
 821 
     | 
    
         
            +
             
     | 
| 
      
 822 
     | 
    
         
            +
                          return index_name_without_column if index_name_exists?(table_name, index_name_without_column, false)
         
     | 
| 
      
 823 
     | 
    
         
            +
                        end
         
     | 
| 
      
 824 
     | 
    
         
            +
             
     | 
| 
      
 825 
     | 
    
         
            +
                        raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
         
     | 
| 
      
 826 
     | 
    
         
            +
                      end
         
     | 
| 
      
 827 
     | 
    
         
            +
             
     | 
| 
      
 828 
     | 
    
         
            +
                      index_name
         
     | 
| 
      
 829 
     | 
    
         
            +
                    end
         
     | 
| 
      
 830 
     | 
    
         
            +
             
     | 
| 
      
 831 
     | 
    
         
            +
                    def columns_for_remove(table_name, *column_names)
         
     | 
| 
      
 832 
     | 
    
         
            +
                      ActiveSupport::Deprecation.warn("columns_for_remove is deprecated and will be removed in the future")
         
     | 
| 
      
 833 
     | 
    
         
            +
                      raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)") if column_names.blank?
         
     | 
| 
      
 834 
     | 
    
         
            +
                      column_names.map {|column_name| quote_column_name(column_name) }
         
     | 
| 
      
 835 
     | 
    
         
            +
                    end
         
     | 
| 
      
 836 
     | 
    
         
            +
             
     | 
| 
      
 837 
     | 
    
         
            +
                    def rename_table_indexes(table_name, new_name)
         
     | 
| 
      
 838 
     | 
    
         
            +
                      indexes(new_name).each do |index|
         
     | 
| 
      
 839 
     | 
    
         
            +
                        generated_index_name = index_name(table_name, column: index.columns)
         
     | 
| 
      
 840 
     | 
    
         
            +
                        if generated_index_name == index.name
         
     | 
| 
      
 841 
     | 
    
         
            +
                          rename_index new_name, generated_index_name, index_name(new_name, column: index.columns)
         
     | 
| 
      
 842 
     | 
    
         
            +
                        end
         
     | 
| 
      
 843 
     | 
    
         
            +
                      end
         
     | 
| 
      
 844 
     | 
    
         
            +
                    end
         
     | 
| 
      
 845 
     | 
    
         
            +
             
     | 
| 
      
 846 
     | 
    
         
            +
                    def rename_column_indexes(table_name, column_name, new_column_name)
         
     | 
| 
      
 847 
     | 
    
         
            +
                      column_name, new_column_name = column_name.to_s, new_column_name.to_s
         
     | 
| 
      
 848 
     | 
    
         
            +
                      indexes(table_name).each do |index|
         
     | 
| 
      
 849 
     | 
    
         
            +
                        next unless index.columns.include?(new_column_name)
         
     | 
| 
      
 850 
     | 
    
         
            +
                        old_columns = index.columns.dup
         
     | 
| 
      
 851 
     | 
    
         
            +
                        old_columns[old_columns.index(new_column_name)] = column_name
         
     | 
| 
      
 852 
     | 
    
         
            +
                        generated_index_name = index_name(table_name, column: old_columns)
         
     | 
| 
      
 853 
     | 
    
         
            +
                        if generated_index_name == index.name
         
     | 
| 
      
 854 
     | 
    
         
            +
                          rename_index table_name, generated_index_name, index_name(table_name, column: index.columns)
         
     | 
| 
      
 855 
     | 
    
         
            +
                        end
         
     | 
| 
      
 856 
     | 
    
         
            +
                      end
         
     | 
| 
      
 857 
     | 
    
         
            +
                    end
         
     | 
| 
      
 858 
     | 
    
         
            +
             
     | 
| 
      
 859 
     | 
    
         
            +
                  private
         
     | 
| 
      
 860 
     | 
    
         
            +
                  def create_table_definition(name, temporary, options)
         
     | 
| 
      
 861 
     | 
    
         
            +
                    TableDefinition.new native_database_types, name, temporary, options
         
     | 
| 
      
 862 
     | 
    
         
            +
                  end
         
     | 
| 
      
 863 
     | 
    
         
            +
             
     | 
| 
      
 864 
     | 
    
         
            +
                  def create_alter_table(name)
         
     | 
| 
      
 865 
     | 
    
         
            +
                    AlterTable.new create_table_definition(name, false, {})
         
     | 
| 
      
 866 
     | 
    
         
            +
                  end
         
     | 
| 
      
 867 
     | 
    
         
            +
             
     | 
| 
      
 868 
     | 
    
         
            +
                  def update_table_definition(table_name, base)
         
     | 
| 
      
 869 
     | 
    
         
            +
                    Table.new(table_name, base)
         
     | 
| 
      
 870 
     | 
    
         
            +
                  end
         
     | 
| 
       541 
871 
     | 
    
         
             
                end
         
     | 
| 
       542 
872 
     | 
    
         
             
              end
         
     | 
| 
       543 
873 
     | 
    
         
             
            end
         
     |