activerecord 5.2.8.1 → 6.0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +938 -573
- data/MIT-LICENSE +3 -1
- data/README.rdoc +5 -3
- data/examples/performance.rb +1 -1
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +4 -3
- data/lib/active_record/association_relation.rb +10 -8
- data/lib/active_record/associations/alias_tracker.rb +0 -1
- data/lib/active_record/associations/association.rb +55 -19
- data/lib/active_record/associations/association_scope.rb +11 -7
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/association.rb +14 -18
- data/lib/active_record/associations/builder/belongs_to.rb +19 -52
- data/lib/active_record/associations/builder/collection_association.rb +3 -13
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +35 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +19 -23
- data/lib/active_record/associations/collection_proxy.rb +14 -17
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +2 -11
- data/lib/active_record/associations/has_many_through_association.rb +14 -14
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
- data/lib/active_record/associations/join_dependency/join_part.rb +4 -4
- data/lib/active_record/associations/join_dependency.rb +47 -30
- data/lib/active_record/associations/preloader/association.rb +61 -41
- data/lib/active_record/associations/preloader/through_association.rb +48 -39
- data/lib/active_record/associations/preloader.rb +44 -33
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +21 -16
- data/lib/active_record/attribute_assignment.rb +7 -11
- data/lib/active_record/attribute_decorators.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
- data/lib/active_record/attribute_methods/dirty.rb +111 -40
- data/lib/active_record/attribute_methods/primary_key.rb +15 -24
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +15 -54
- data/lib/active_record/attribute_methods/serialization.rb +1 -2
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
- data/lib/active_record/attribute_methods/write.rb +17 -25
- data/lib/active_record/attribute_methods.rb +28 -100
- data/lib/active_record/attributes.rb +13 -1
- data/lib/active_record/autosave_association.rb +12 -14
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +6 -21
- data/lib/active_record/coders/yaml_column.rb +15 -6
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +109 -18
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +77 -17
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +105 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
- data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
- data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -217
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
- data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +137 -147
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +139 -26
- data/lib/active_record/core.rb +108 -67
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +78 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +44 -7
- data/lib/active_record/errors.rb +15 -7
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +144 -474
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +13 -6
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +68 -16
- data/lib/active_record/internal_metadata.rb +11 -3
- data/lib/active_record/locking/optimistic.rb +14 -7
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +8 -27
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/migration/command_recorder.rb +54 -22
- data/lib/active_record/migration/compatibility.rb +79 -52
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +104 -85
- data/lib/active_record/model_schema.rb +62 -11
- data/lib/active_record/nested_attributes.rb +2 -4
- data/lib/active_record/no_touching.rb +9 -2
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +232 -29
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +33 -21
- data/lib/active_record/railtie.rb +80 -61
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +199 -46
- data/lib/active_record/reflection.rb +51 -51
- data/lib/active_record/relation/batches.rb +13 -11
- data/lib/active_record/relation/calculations.rb +55 -49
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +23 -28
- data/lib/active_record/relation/from_clause.rb +4 -0
- data/lib/active_record/relation/merger.rb +12 -17
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder.rb +5 -11
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +234 -69
- data/lib/active_record/relation/spawn_methods.rb +1 -2
- data/lib/active_record/relation/where_clause.rb +14 -11
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/relation.rb +326 -81
- data/lib/active_record/result.rb +30 -12
- data/lib/active_record/sanitization.rb +32 -40
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +22 -7
- data/lib/active_record/schema_migration.rb +6 -2
- data/lib/active_record/scoping/default.rb +4 -6
- data/lib/active_record/scoping/named.rb +25 -16
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/statement_cache.rb +30 -3
- data/lib/active_record/store.rb +87 -8
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +23 -15
- data/lib/active_record/tasks/database_tasks.rb +194 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +243 -0
- data/lib/active_record/timestamp.rb +39 -26
- data/lib/active_record/touch_later.rb +5 -4
- data/lib/active_record/transactions.rb +64 -73
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +0 -1
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +3 -5
- data/lib/active_record/type_caster/connection.rb +15 -14
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/associated.rb +0 -1
- data/lib/active_record/validations/uniqueness.rb +15 -27
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +10 -2
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +256 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +203 -0
- data/lib/arel/visitors/dot.rb +296 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +156 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +158 -0
- data/lib/arel/visitors/oracle12.rb +65 -0
- data/lib/arel/visitors/postgresql.rb +109 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +888 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors/where_sql.rb +22 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +62 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
- data/lib/rails/generators/active_record/migration.rb +14 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +113 -26
- data/lib/active_record/collection_cache_key.rb +0 -53
| @@ -7,7 +7,8 @@ module ActiveRecord | |
| 7 7 | 
             
                module QueryCache
         | 
| 8 8 | 
             
                  class << self
         | 
| 9 9 | 
             
                    def included(base) #:nodoc:
         | 
| 10 | 
            -
                      dirties_query_cache base, :insert, :update, :delete, : | 
| 10 | 
            +
                      dirties_query_cache base, :insert, :update, :delete, :truncate, :truncate_tables,
         | 
| 11 | 
            +
                        :rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
         | 
| 11 12 |  | 
| 12 13 | 
             
                      base.set_callback :checkout, :after, :configure_query_cache!
         | 
| 13 14 | 
             
                      base.set_callback :checkin, :after, :disable_query_cache!
         | 
| @@ -17,7 +18,7 @@ module ActiveRecord | |
| 17 18 | 
             
                      method_names.each do |method_name|
         | 
| 18 19 | 
             
                        base.class_eval <<-end_code, __FILE__, __LINE__ + 1
         | 
| 19 20 | 
             
                          def #{method_name}(*)
         | 
| 20 | 
            -
                             | 
| 21 | 
            +
                            ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
         | 
| 21 22 | 
             
                            super
         | 
| 22 23 | 
             
                          end
         | 
| 23 24 | 
             
                        end_code
         | 
| @@ -108,19 +109,13 @@ module ActiveRecord | |
| 108 109 | 
             
                  end
         | 
| 109 110 |  | 
| 110 111 | 
             
                  private
         | 
| 111 | 
            -
             | 
| 112 112 | 
             
                    def cache_sql(sql, name, binds)
         | 
| 113 113 | 
             
                      @lock.synchronize do
         | 
| 114 114 | 
             
                        result =
         | 
| 115 115 | 
             
                          if @query_cache[sql].key?(binds)
         | 
| 116 116 | 
             
                            ActiveSupport::Notifications.instrument(
         | 
| 117 117 | 
             
                              "sql.active_record",
         | 
| 118 | 
            -
                              sql | 
| 119 | 
            -
                              binds: binds,
         | 
| 120 | 
            -
                              type_casted_binds: -> { type_casted_binds(binds) },
         | 
| 121 | 
            -
                              name: name,
         | 
| 122 | 
            -
                              connection_id: object_id,
         | 
| 123 | 
            -
                              cached: true,
         | 
| 118 | 
            +
                              cache_notification_info(sql, name, binds)
         | 
| 124 119 | 
             
                            )
         | 
| 125 120 | 
             
                            @query_cache[sql][binds]
         | 
| 126 121 | 
             
                          else
         | 
| @@ -130,6 +125,20 @@ module ActiveRecord | |
| 130 125 | 
             
                      end
         | 
| 131 126 | 
             
                    end
         | 
| 132 127 |  | 
| 128 | 
            +
                    # Database adapters can override this method to
         | 
| 129 | 
            +
                    # provide custom cache information.
         | 
| 130 | 
            +
                    def cache_notification_info(sql, name, binds)
         | 
| 131 | 
            +
                      {
         | 
| 132 | 
            +
                        sql: sql,
         | 
| 133 | 
            +
                        binds: binds,
         | 
| 134 | 
            +
                        type_casted_binds: -> { type_casted_binds(binds) },
         | 
| 135 | 
            +
                        name: name,
         | 
| 136 | 
            +
                        connection_id: object_id,
         | 
| 137 | 
            +
                        connection: self,
         | 
| 138 | 
            +
                        cached: true
         | 
| 139 | 
            +
                      }
         | 
| 140 | 
            +
                    end
         | 
| 141 | 
            +
             | 
| 133 142 | 
             
                    # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
         | 
| 134 143 | 
             
                    # queries should not be cached.
         | 
| 135 144 | 
             
                    def locked?(arel)
         | 
| @@ -60,7 +60,7 @@ module ActiveRecord | |
| 60 60 | 
             
                  # Quotes a string, escaping any ' (single quote) and \ (backslash)
         | 
| 61 61 | 
             
                  # characters.
         | 
| 62 62 | 
             
                  def quote_string(s)
         | 
| 63 | 
            -
                    s.gsub('\\' | 
| 63 | 
            +
                    s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
         | 
| 64 64 | 
             
                  end
         | 
| 65 65 |  | 
| 66 66 | 
             
                  # Quotes the column name. Defaults to no quoting.
         | 
| @@ -95,7 +95,7 @@ module ActiveRecord | |
| 95 95 | 
             
                  end
         | 
| 96 96 |  | 
| 97 97 | 
             
                  def quoted_true
         | 
| 98 | 
            -
                    "TRUE" | 
| 98 | 
            +
                    "TRUE"
         | 
| 99 99 | 
             
                  end
         | 
| 100 100 |  | 
| 101 101 | 
             
                  def unquoted_true
         | 
| @@ -103,7 +103,7 @@ module ActiveRecord | |
| 103 103 | 
             
                  end
         | 
| 104 104 |  | 
| 105 105 | 
             
                  def quoted_false
         | 
| 106 | 
            -
                    "FALSE" | 
| 106 | 
            +
                    "FALSE"
         | 
| 107 107 | 
             
                  end
         | 
| 108 108 |  | 
| 109 109 | 
             
                  def unquoted_false
         | 
| @@ -138,15 +138,81 @@ module ActiveRecord | |
| 138 138 | 
             
                    "'#{quote_string(value.to_s)}'"
         | 
| 139 139 | 
             
                  end
         | 
| 140 140 |  | 
| 141 | 
            -
                  def  | 
| 142 | 
            -
                     | 
| 143 | 
            -
             | 
| 144 | 
            -
                     | 
| 145 | 
            -
             | 
| 146 | 
            -
                     | 
| 141 | 
            +
                  def sanitize_as_sql_comment(value) # :nodoc:
         | 
| 142 | 
            +
                    # Sanitize a string to appear within a SQL comment
         | 
| 143 | 
            +
                    # For compatibility, this also surrounding "/*+", "/*", and "*/"
         | 
| 144 | 
            +
                    # charcacters, possibly with single surrounding space.
         | 
| 145 | 
            +
                    # Then follows that by replacing any internal "*/" or "/ *" with
         | 
| 146 | 
            +
                    # "* /" or "/ *"
         | 
| 147 | 
            +
                    comment = value.to_s.dup
         | 
| 148 | 
            +
                    comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
         | 
| 149 | 
            +
                    comment.gsub!("*/", "* /")
         | 
| 150 | 
            +
                    comment.gsub!("/*", "/ *")
         | 
| 151 | 
            +
                    comment
         | 
| 152 | 
            +
                  end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                  def column_name_matcher # :nodoc:
         | 
| 155 | 
            +
                    COLUMN_NAME
         | 
| 147 156 | 
             
                  end
         | 
| 148 157 |  | 
| 158 | 
            +
                  def column_name_with_order_matcher # :nodoc:
         | 
| 159 | 
            +
                    COLUMN_NAME_WITH_ORDER
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                  # Regexp for column names (with or without a table name prefix).
         | 
| 163 | 
            +
                  # Matches the following:
         | 
| 164 | 
            +
                  #
         | 
| 165 | 
            +
                  #   "#{table_name}.#{column_name}"
         | 
| 166 | 
            +
                  #   "#{column_name}"
         | 
| 167 | 
            +
                  COLUMN_NAME = /
         | 
| 168 | 
            +
                    \A
         | 
| 169 | 
            +
                    (
         | 
| 170 | 
            +
                      (?:
         | 
| 171 | 
            +
                        # table_name.column_name | function(one or no argument)
         | 
| 172 | 
            +
                        ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
         | 
| 173 | 
            +
                      )
         | 
| 174 | 
            +
                      (?:\s+AS\s+\w+)?
         | 
| 175 | 
            +
                    )
         | 
| 176 | 
            +
                    (?:\s*,\s*\g<1>)*
         | 
| 177 | 
            +
                    \z
         | 
| 178 | 
            +
                  /ix
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                  # Regexp for column names with order (with or without a table name prefix,
         | 
| 181 | 
            +
                  # with or without various order modifiers). Matches the following:
         | 
| 182 | 
            +
                  #
         | 
| 183 | 
            +
                  #   "#{table_name}.#{column_name}"
         | 
| 184 | 
            +
                  #   "#{table_name}.#{column_name} #{direction}"
         | 
| 185 | 
            +
                  #   "#{table_name}.#{column_name} #{direction} NULLS FIRST"
         | 
| 186 | 
            +
                  #   "#{table_name}.#{column_name} NULLS LAST"
         | 
| 187 | 
            +
                  #   "#{column_name}"
         | 
| 188 | 
            +
                  #   "#{column_name} #{direction}"
         | 
| 189 | 
            +
                  #   "#{column_name} #{direction} NULLS FIRST"
         | 
| 190 | 
            +
                  #   "#{column_name} NULLS LAST"
         | 
| 191 | 
            +
                  COLUMN_NAME_WITH_ORDER = /
         | 
| 192 | 
            +
                    \A
         | 
| 193 | 
            +
                    (
         | 
| 194 | 
            +
                      (?:
         | 
| 195 | 
            +
                        # table_name.column_name | function(one or no argument)
         | 
| 196 | 
            +
                        ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
         | 
| 197 | 
            +
                      )
         | 
| 198 | 
            +
                      (?:\s+ASC|\s+DESC)?
         | 
| 199 | 
            +
                      (?:\s+NULLS\s+(?:FIRST|LAST))?
         | 
| 200 | 
            +
                    )
         | 
| 201 | 
            +
                    (?:\s*,\s*\g<1>)*
         | 
| 202 | 
            +
                    \z
         | 
| 203 | 
            +
                  /ix
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                  private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
         | 
| 206 | 
            +
             | 
| 149 207 | 
             
                  private
         | 
| 208 | 
            +
                    def type_casted_binds(binds)
         | 
| 209 | 
            +
                      if binds.first.is_a?(Array)
         | 
| 210 | 
            +
                        binds.map { |column, value| type_cast(value, column) }
         | 
| 211 | 
            +
                      else
         | 
| 212 | 
            +
                        binds.map { |attr| type_cast(attr.value_for_database) }
         | 
| 213 | 
            +
                      end
         | 
| 214 | 
            +
                    end
         | 
| 215 | 
            +
             | 
| 150 216 | 
             
                    def lookup_cast_type(sql_type)
         | 
| 151 217 | 
             
                      type_map.lookup(sql_type)
         | 
| 152 218 | 
             
                    end
         | 
| @@ -157,13 +223,9 @@ module ActiveRecord | |
| 157 223 | 
             
                      end
         | 
| 158 224 | 
             
                    end
         | 
| 159 225 |  | 
| 160 | 
            -
                    def types_which_need_no_typecasting
         | 
| 161 | 
            -
                      [nil, Numeric, String]
         | 
| 162 | 
            -
                    end
         | 
| 163 | 
            -
             | 
| 164 226 | 
             
                    def _quote(value)
         | 
| 165 227 | 
             
                      case value
         | 
| 166 | 
            -
                      when String, ActiveSupport::Multibyte::Chars
         | 
| 228 | 
            +
                      when String, Symbol, ActiveSupport::Multibyte::Chars
         | 
| 167 229 | 
             
                        "'#{quote_string(value.to_s)}'"
         | 
| 168 230 | 
             
                      when true       then quoted_true
         | 
| 169 231 | 
             
                      when false      then quoted_false
         | 
| @@ -174,7 +236,6 @@ module ActiveRecord | |
| 174 236 | 
             
                      when Type::Binary::Data then quoted_binary(value)
         | 
| 175 237 | 
             
                      when Type::Time::Value then "'#{quoted_time(value)}'"
         | 
| 176 238 | 
             
                      when Date, Time then "'#{quoted_date(value)}'"
         | 
| 177 | 
            -
                      when Symbol     then "'#{quote_string(value.to_s)}'"
         | 
| 178 239 | 
             
                      when Class      then "'#{value}'"
         | 
| 179 240 | 
             
                      else raise TypeError, "can't quote #{value.class.name}"
         | 
| 180 241 | 
             
                      end
         | 
| @@ -188,10 +249,9 @@ module ActiveRecord | |
| 188 249 | 
             
                      when false      then unquoted_false
         | 
| 189 250 | 
             
                      # BigDecimals need to be put in a non-normalized form and quoted.
         | 
| 190 251 | 
             
                      when BigDecimal then value.to_s("F")
         | 
| 252 | 
            +
                      when nil, Numeric, String then value
         | 
| 191 253 | 
             
                      when Type::Time::Value then quoted_time(value)
         | 
| 192 254 | 
             
                      when Date, Time then quoted_date(value)
         | 
| 193 | 
            -
                      when *types_which_need_no_typecasting
         | 
| 194 | 
            -
                        value
         | 
| 195 255 | 
             
                      else raise TypeError
         | 
| 196 256 | 
             
                      end
         | 
| 197 257 | 
             
                    end
         | 
| @@ -1,7 +1,5 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require "active_support/core_ext/string/strip"
         | 
| 4 | 
            -
             | 
| 5 3 | 
             
            module ActiveRecord
         | 
| 6 4 | 
             
              module ConnectionAdapters
         | 
| 7 5 | 
             
                class AbstractAdapter
         | 
| @@ -17,32 +15,32 @@ module ActiveRecord | |
| 17 15 | 
             
                    end
         | 
| 18 16 |  | 
| 19 17 | 
             
                    delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
         | 
| 20 | 
            -
                      :options_include_default?, :supports_indexes_in_create?, : | 
| 21 | 
            -
             | 
| 22 | 
            -
                      :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options
         | 
| 18 | 
            +
                      :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?, :foreign_key_options,
         | 
| 19 | 
            +
                      to: :@conn, private: true
         | 
| 23 20 |  | 
| 24 21 | 
             
                    private
         | 
| 25 | 
            -
             | 
| 26 22 | 
             
                      def visit_AlterTable(o)
         | 
| 27 | 
            -
                        sql = "ALTER TABLE #{quote_table_name(o.name)} " | 
| 23 | 
            +
                        sql = +"ALTER TABLE #{quote_table_name(o.name)} "
         | 
| 28 24 | 
             
                        sql << o.adds.map { |col| accept col }.join(" ")
         | 
| 29 25 | 
             
                        sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
         | 
| 30 26 | 
             
                        sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
         | 
| 31 27 | 
             
                      end
         | 
| 32 28 |  | 
| 33 29 | 
             
                      def visit_ColumnDefinition(o)
         | 
| 34 | 
            -
                        o.sql_type = type_to_sql(o.type, o.options)
         | 
| 35 | 
            -
                        column_sql = "#{quote_column_name(o.name)} #{o.sql_type}" | 
| 30 | 
            +
                        o.sql_type = type_to_sql(o.type, **o.options)
         | 
| 31 | 
            +
                        column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
         | 
| 36 32 | 
             
                        add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
         | 
| 37 33 | 
             
                        column_sql
         | 
| 38 34 | 
             
                      end
         | 
| 39 35 |  | 
| 40 36 | 
             
                      def visit_AddColumnDefinition(o)
         | 
| 41 | 
            -
                        "ADD #{accept(o.column)}" | 
| 37 | 
            +
                        +"ADD #{accept(o.column)}"
         | 
| 42 38 | 
             
                      end
         | 
| 43 39 |  | 
| 44 40 | 
             
                      def visit_TableDefinition(o)
         | 
| 45 | 
            -
                        create_sql = "CREATE#{ | 
| 41 | 
            +
                        create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
         | 
| 42 | 
            +
                        create_sql << "IF NOT EXISTS " if o.if_not_exists
         | 
| 43 | 
            +
                        create_sql << "#{quote_table_name(o.name)} "
         | 
| 46 44 |  | 
| 47 45 | 
             
                        statements = o.columns.map { |c| accept c }
         | 
| 48 46 | 
             
                        statements << accept(o.primary_keys) if o.primary_keys
         | 
| @@ -51,7 +49,7 @@ module ActiveRecord | |
| 51 49 | 
             
                          statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
         | 
| 52 50 | 
             
                        end
         | 
| 53 51 |  | 
| 54 | 
            -
                        if  | 
| 52 | 
            +
                        if supports_foreign_keys?
         | 
| 55 53 | 
             
                          statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
         | 
| 56 54 | 
             
                        end
         | 
| 57 55 |  | 
| @@ -66,7 +64,7 @@ module ActiveRecord | |
| 66 64 | 
             
                      end
         | 
| 67 65 |  | 
| 68 66 | 
             
                      def visit_ForeignKeyDefinition(o)
         | 
| 69 | 
            -
                        sql =  | 
| 67 | 
            +
                        sql = +<<~SQL
         | 
| 70 68 | 
             
                          CONSTRAINT #{quote_column_name(o.name)}
         | 
| 71 69 | 
             
                          FOREIGN KEY (#{quote_column_name(o.column)})
         | 
| 72 70 | 
             
                            REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
         | 
| @@ -122,7 +120,15 @@ module ActiveRecord | |
| 122 120 | 
             
                        sql
         | 
| 123 121 | 
             
                      end
         | 
| 124 122 |  | 
| 123 | 
            +
                      # Returns any SQL string to go between CREATE and TABLE. May be nil.
         | 
| 124 | 
            +
                      def table_modifier_in_create(o)
         | 
| 125 | 
            +
                        " TEMPORARY" if o.temporary
         | 
| 126 | 
            +
                      end
         | 
| 127 | 
            +
             | 
| 125 128 | 
             
                      def foreign_key_in_create(from_table, to_table, options)
         | 
| 129 | 
            +
                        prefix = ActiveRecord::Base.table_name_prefix
         | 
| 130 | 
            +
                        suffix = ActiveRecord::Base.table_name_suffix
         | 
| 131 | 
            +
                        to_table = "#{prefix}#{to_table}#{suffix}"
         | 
| 126 132 | 
             
                        options = foreign_key_options(from_table, to_table, options)
         | 
| 127 133 | 
             
                        accept ForeignKeyDefinition.new(from_table, to_table, options)
         | 
| 128 134 | 
             
                      end
         | 
| @@ -133,7 +139,7 @@ module ActiveRecord | |
| 133 139 | 
             
                        when :cascade  then "ON #{action} CASCADE"
         | 
| 134 140 | 
             
                        when :restrict then "ON #{action} RESTRICT"
         | 
| 135 141 | 
             
                        else
         | 
| 136 | 
            -
                          raise ArgumentError,  | 
| 142 | 
            +
                          raise ArgumentError, <<~MSG
         | 
| 137 143 | 
             
                            '#{dependency}' is not supported for :on_update or :on_delete.
         | 
| 138 144 | 
             
                            Supported values are: :nullify, :cascade, :restrict
         | 
| 139 145 | 
             
                          MSG
         | 
| @@ -63,6 +63,10 @@ module ActiveRecord | |
| 63 63 | 
             
                      end
         | 
| 64 64 | 
             
                    CODE
         | 
| 65 65 | 
             
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def aliased_types(name, fallback)
         | 
| 68 | 
            +
                    "timestamp" == name ? :datetime : fallback
         | 
| 69 | 
            +
                  end
         | 
| 66 70 | 
             
                end
         | 
| 67 71 |  | 
| 68 72 | 
             
                AddColumnDefinition = Struct.new(:column) # :nodoc:
         | 
| @@ -101,13 +105,14 @@ module ActiveRecord | |
| 101 105 | 
             
                  end
         | 
| 102 106 | 
             
                  alias validated? validate?
         | 
| 103 107 |  | 
| 104 | 
            -
                  def  | 
| 105 | 
            -
                    if  | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 108 | 
            +
                  def export_name_on_schema_dump?
         | 
| 109 | 
            +
                    !ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name
         | 
| 110 | 
            +
                  end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  def defined_for?(to_table: nil, validate: nil, **options)
         | 
| 113 | 
            +
                    (to_table.nil? || to_table.to_s == self.to_table) &&
         | 
| 114 | 
            +
                      (validate.nil? || validate == options.fetch(:validate, validate)) &&
         | 
| 115 | 
            +
                      options.all? { |k, v| self.options[k].to_s == v.to_s }
         | 
| 111 116 | 
             
                  end
         | 
| 112 117 |  | 
| 113 118 | 
             
                  private
         | 
| @@ -139,7 +144,8 @@ module ActiveRecord | |
| 139 144 |  | 
| 140 145 | 
             
                  def add_to(table)
         | 
| 141 146 | 
             
                    columns.each do |column_options|
         | 
| 142 | 
            -
                       | 
| 147 | 
            +
                      kwargs = column_options.extract_options!
         | 
| 148 | 
            +
                      table.column(*column_options, **kwargs)
         | 
| 143 149 | 
             
                    end
         | 
| 144 150 |  | 
| 145 151 | 
             
                    if index
         | 
| @@ -147,17 +153,12 @@ module ActiveRecord | |
| 147 153 | 
             
                    end
         | 
| 148 154 |  | 
| 149 155 | 
             
                    if foreign_key
         | 
| 150 | 
            -
                      table.foreign_key(foreign_table_name, foreign_key_options)
         | 
| 156 | 
            +
                      table.foreign_key(foreign_table_name, **foreign_key_options)
         | 
| 151 157 | 
             
                    end
         | 
| 152 158 | 
             
                  end
         | 
| 153 159 |  | 
| 154 | 
            -
                  # TODO Change this to private once we've dropped Ruby 2.2 support.
         | 
| 155 | 
            -
                  # Workaround for Ruby 2.2 "private attribute?" warning.
         | 
| 156 | 
            -
                  protected
         | 
| 157 | 
            -
             | 
| 158 | 
            -
                    attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
         | 
| 159 | 
            -
             | 
| 160 160 | 
             
                  private
         | 
| 161 | 
            +
                    attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
         | 
| 161 162 |  | 
| 162 163 | 
             
                    def as_options(value)
         | 
| 163 164 | 
             
                      value.is_a?(Hash) ? value : {}
         | 
| @@ -199,41 +200,44 @@ module ActiveRecord | |
| 199 200 | 
             
                end
         | 
| 200 201 |  | 
| 201 202 | 
             
                module ColumnMethods
         | 
| 203 | 
            +
                  extend ActiveSupport::Concern
         | 
| 204 | 
            +
             | 
| 202 205 | 
             
                  # Appends a primary key definition to the table definition.
         | 
| 203 206 | 
             
                  # Can be called multiple times, but this is probably not a good idea.
         | 
| 204 207 | 
             
                  def primary_key(name, type = :primary_key, **options)
         | 
| 205 | 
            -
                    column(name, type, options.merge(primary_key: true))
         | 
| 208 | 
            +
                    column(name, type, **options.merge(primary_key: true))
         | 
| 206 209 | 
             
                  end
         | 
| 207 210 |  | 
| 211 | 
            +
                  ##
         | 
| 212 | 
            +
                  # :method: column
         | 
| 213 | 
            +
                  # :call-seq: column(name, type, **options)
         | 
| 214 | 
            +
                  #
         | 
| 208 215 | 
             
                  # Appends a column or columns of a specified type.
         | 
| 209 216 | 
             
                  #
         | 
| 210 217 | 
             
                  #  t.string(:goat)
         | 
| 211 218 | 
             
                  #  t.string(:goat, :sheep)
         | 
| 212 219 | 
             
                  #
         | 
| 213 220 | 
             
                  # See TableDefinition#column
         | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
                    :binary,
         | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
                    : | 
| 220 | 
            -
             | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 223 | 
            -
                    : | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 230 | 
            -
             | 
| 231 | 
            -
                      def #{column_type}(*args, **options)
         | 
| 232 | 
            -
                        args.each { |name| column(name, :#{column_type}, options) }
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                  included do
         | 
| 223 | 
            +
                    define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
         | 
| 224 | 
            +
                      :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                    alias :numeric :decimal
         | 
| 227 | 
            +
                  end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                  class_methods do
         | 
| 230 | 
            +
                    private def define_column_methods(*column_types) # :nodoc:
         | 
| 231 | 
            +
                      column_types.each do |column_type|
         | 
| 232 | 
            +
                        module_eval <<-RUBY, __FILE__, __LINE__ + 1
         | 
| 233 | 
            +
                          def #{column_type}(*names, **options)
         | 
| 234 | 
            +
                            raise ArgumentError, "Missing column name(s) for #{column_type}" if names.empty?
         | 
| 235 | 
            +
                            names.each { |name| column(name, :#{column_type}, **options) }
         | 
| 236 | 
            +
                          end
         | 
| 237 | 
            +
                        RUBY
         | 
| 233 238 | 
             
                      end
         | 
| 234 | 
            -
                     | 
| 239 | 
            +
                    end
         | 
| 235 240 | 
             
                  end
         | 
| 236 | 
            -
                  alias_method :numeric, :decimal
         | 
| 237 241 | 
             
                end
         | 
| 238 242 |  | 
| 239 243 | 
             
                # Represents the schema of an SQL table in an abstract way. This class
         | 
| @@ -257,15 +261,25 @@ module ActiveRecord | |
| 257 261 | 
             
                class TableDefinition
         | 
| 258 262 | 
             
                  include ColumnMethods
         | 
| 259 263 |  | 
| 260 | 
            -
                   | 
| 261 | 
            -
                  attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
         | 
| 264 | 
            +
                  attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
         | 
| 262 265 |  | 
| 263 | 
            -
                  def initialize( | 
| 266 | 
            +
                  def initialize(
         | 
| 267 | 
            +
                    conn,
         | 
| 268 | 
            +
                    name,
         | 
| 269 | 
            +
                    temporary: false,
         | 
| 270 | 
            +
                    if_not_exists: false,
         | 
| 271 | 
            +
                    options: nil,
         | 
| 272 | 
            +
                    as: nil,
         | 
| 273 | 
            +
                    comment: nil,
         | 
| 274 | 
            +
                    **
         | 
| 275 | 
            +
                  )
         | 
| 276 | 
            +
                    @conn = conn
         | 
| 264 277 | 
             
                    @columns_hash = {}
         | 
| 265 278 | 
             
                    @indexes = []
         | 
| 266 279 | 
             
                    @foreign_keys = []
         | 
| 267 280 | 
             
                    @primary_keys = nil
         | 
| 268 281 | 
             
                    @temporary = temporary
         | 
| 282 | 
            +
                    @if_not_exists = if_not_exists
         | 
| 269 283 | 
             
                    @options = options
         | 
| 270 284 | 
             
                    @as = as
         | 
| 271 285 | 
             
                    @name = name
         | 
| @@ -349,21 +363,24 @@ module ActiveRecord | |
| 349 363 | 
             
                  #
         | 
| 350 364 | 
             
                  #   create_table :taggings do |t|
         | 
| 351 365 | 
             
                  #     t.references :tag, index: { name: 'index_taggings_on_tag_id' }
         | 
| 352 | 
            -
                  #     t.references :tagger, polymorphic: true | 
| 353 | 
            -
                  #     t.references :taggable, polymorphic: { default: 'Photo' }
         | 
| 366 | 
            +
                  #     t.references :tagger, polymorphic: true
         | 
| 367 | 
            +
                  #     t.references :taggable, polymorphic: { default: 'Photo' }, index: false
         | 
| 354 368 | 
             
                  #   end
         | 
| 355 | 
            -
                  def column(name, type, options | 
| 369 | 
            +
                  def column(name, type, **options)
         | 
| 356 370 | 
             
                    name = name.to_s
         | 
| 357 371 | 
             
                    type = type.to_sym if type
         | 
| 358 | 
            -
                    options = options.dup
         | 
| 359 372 |  | 
| 360 | 
            -
                    if @columns_hash[name] | 
| 361 | 
            -
                       | 
| 373 | 
            +
                    if @columns_hash[name]
         | 
| 374 | 
            +
                      if @columns_hash[name].primary_key?
         | 
| 375 | 
            +
                        raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
         | 
| 376 | 
            +
                      else
         | 
| 377 | 
            +
                        raise ArgumentError, "you can't define an already defined column '#{name}'."
         | 
| 378 | 
            +
                      end
         | 
| 362 379 | 
             
                    end
         | 
| 363 380 |  | 
| 364 381 | 
             
                    index_options = options.delete(:index)
         | 
| 365 382 | 
             
                    index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
         | 
| 366 | 
            -
                    @columns_hash[name] = new_column_definition(name, type, options)
         | 
| 383 | 
            +
                    @columns_hash[name] = new_column_definition(name, type, **options)
         | 
| 367 384 | 
             
                    self
         | 
| 368 385 | 
             
                  end
         | 
| 369 386 |  | 
| @@ -381,11 +398,8 @@ module ActiveRecord | |
| 381 398 | 
             
                    indexes << [column_name, options]
         | 
| 382 399 | 
             
                  end
         | 
| 383 400 |  | 
| 384 | 
            -
                  def foreign_key(table_name, options | 
| 385 | 
            -
                     | 
| 386 | 
            -
                    table_name_suffix = ActiveRecord::Base.table_name_suffix
         | 
| 387 | 
            -
                    table_name = "#{table_name_prefix}#{table_name}#{table_name_suffix}"
         | 
| 388 | 
            -
                    foreign_keys.push([table_name, options])
         | 
| 401 | 
            +
                  def foreign_key(table_name, **options) # :nodoc:
         | 
| 402 | 
            +
                    foreign_keys << [table_name, options]
         | 
| 389 403 | 
             
                  end
         | 
| 390 404 |  | 
| 391 405 | 
             
                  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
         | 
| @@ -395,19 +409,24 @@ module ActiveRecord | |
| 395 409 | 
             
                  def timestamps(**options)
         | 
| 396 410 | 
             
                    options[:null] = false if options[:null].nil?
         | 
| 397 411 |  | 
| 398 | 
            -
                     | 
| 399 | 
            -
             | 
| 412 | 
            +
                    if !options.key?(:precision) && @conn.supports_datetime_with_precision?
         | 
| 413 | 
            +
                      options[:precision] = 6
         | 
| 414 | 
            +
                    end
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                    column(:created_at, :datetime, **options)
         | 
| 417 | 
            +
                    column(:updated_at, :datetime, **options)
         | 
| 400 418 | 
             
                  end
         | 
| 401 419 |  | 
| 402 420 | 
             
                  # Adds a reference.
         | 
| 403 421 | 
             
                  #
         | 
| 404 422 | 
             
                  #  t.references(:user)
         | 
| 405 423 | 
             
                  #  t.belongs_to(:supplier, foreign_key: true)
         | 
| 424 | 
            +
                  #  t.belongs_to(:supplier, foreign_key: true, type: :integer)
         | 
| 406 425 | 
             
                  #
         | 
| 407 426 | 
             
                  # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
         | 
| 408 427 | 
             
                  def references(*args, **options)
         | 
| 409 428 | 
             
                    args.each do |ref_name|
         | 
| 410 | 
            -
                      ReferenceDefinition.new(ref_name, options).add_to(self)
         | 
| 429 | 
            +
                      ReferenceDefinition.new(ref_name, **options).add_to(self)
         | 
| 411 430 | 
             
                    end
         | 
| 412 431 | 
             
                  end
         | 
| 413 432 | 
             
                  alias :belongs_to :references
         | 
| @@ -462,10 +481,10 @@ module ActiveRecord | |
| 462 481 | 
             
                    @foreign_key_drops << name
         | 
| 463 482 | 
             
                  end
         | 
| 464 483 |  | 
| 465 | 
            -
                  def add_column(name, type, options)
         | 
| 484 | 
            +
                  def add_column(name, type, **options)
         | 
| 466 485 | 
             
                    name = name.to_s
         | 
| 467 486 | 
             
                    type = type.to_sym
         | 
| 468 | 
            -
                    @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, options))
         | 
| 487 | 
            +
                    @adds << AddColumnDefinition.new(@td.new_column_definition(name, type, **options))
         | 
| 469 488 | 
             
                  end
         | 
| 470 489 | 
             
                end
         | 
| 471 490 |  | 
| @@ -502,6 +521,7 @@ module ActiveRecord | |
| 502 521 | 
             
                #     t.json
         | 
| 503 522 | 
             
                #     t.virtual
         | 
| 504 523 | 
             
                #     t.remove
         | 
| 524 | 
            +
                #     t.remove_foreign_key
         | 
| 505 525 | 
             
                #     t.remove_references
         | 
| 506 526 | 
             
                #     t.remove_belongs_to
         | 
| 507 527 | 
             
                #     t.remove_index
         | 
| @@ -523,8 +543,10 @@ module ActiveRecord | |
| 523 543 | 
             
                  #  t.column(:name, :string)
         | 
| 524 544 | 
             
                  #
         | 
| 525 545 | 
             
                  # See TableDefinition#column for details of the options you can use.
         | 
| 526 | 
            -
                  def column(column_name, type, options | 
| 527 | 
            -
                     | 
| 546 | 
            +
                  def column(column_name, type, **options)
         | 
| 547 | 
            +
                    index_options = options.delete(:index)
         | 
| 548 | 
            +
                    @base.add_column(name, column_name, type, **options)
         | 
| 549 | 
            +
                    index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
         | 
| 528 550 | 
             
                  end
         | 
| 529 551 |  | 
| 530 552 | 
             
                  # Checks to see if a column exists.
         | 
| @@ -532,8 +554,8 @@ module ActiveRecord | |
| 532 554 | 
             
                  #  t.string(:name) unless t.column_exists?(:name, :string)
         | 
| 533 555 | 
             
                  #
         | 
| 534 556 | 
             
                  # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
         | 
| 535 | 
            -
                  def column_exists?(column_name, type = nil, options | 
| 536 | 
            -
                    @base.column_exists?(name, column_name, type, options)
         | 
| 557 | 
            +
                  def column_exists?(column_name, type = nil, **options)
         | 
| 558 | 
            +
                    @base.column_exists?(name, column_name, type, **options)
         | 
| 537 559 | 
             
                  end
         | 
| 538 560 |  | 
| 539 561 | 
             
                  # Adds a new index to the table. +column_name+ can be a single Symbol, or
         | 
| @@ -573,8 +595,8 @@ module ActiveRecord | |
| 573 595 | 
             
                  #  t.timestamps(null: false)
         | 
| 574 596 | 
             
                  #
         | 
| 575 597 | 
             
                  # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
         | 
| 576 | 
            -
                  def timestamps(options | 
| 577 | 
            -
                    @base.add_timestamps(name, options)
         | 
| 598 | 
            +
                  def timestamps(**options)
         | 
| 599 | 
            +
                    @base.add_timestamps(name, **options)
         | 
| 578 600 | 
             
                  end
         | 
| 579 601 |  | 
| 580 602 | 
             
                  # Changes the column's definition according to the new options.
         | 
| @@ -624,8 +646,8 @@ module ActiveRecord | |
| 624 646 | 
             
                  #  t.remove_timestamps
         | 
| 625 647 | 
             
                  #
         | 
| 626 648 | 
             
                  # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
         | 
| 627 | 
            -
                  def remove_timestamps(options | 
| 628 | 
            -
                    @base.remove_timestamps(name, options)
         | 
| 649 | 
            +
                  def remove_timestamps(**options)
         | 
| 650 | 
            +
                    @base.remove_timestamps(name, **options)
         | 
| 629 651 | 
             
                  end
         | 
| 630 652 |  | 
| 631 653 | 
             
                  # Renames a column.
         | 
| @@ -645,7 +667,7 @@ module ActiveRecord | |
| 645 667 | 
             
                  # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
         | 
| 646 668 | 
             
                  def references(*args, **options)
         | 
| 647 669 | 
             
                    args.each do |ref_name|
         | 
| 648 | 
            -
                      @base.add_reference(name, ref_name, options)
         | 
| 670 | 
            +
                      @base.add_reference(name, ref_name, **options)
         | 
| 649 671 | 
             
                    end
         | 
| 650 672 | 
             
                  end
         | 
| 651 673 | 
             
                  alias :belongs_to :references
         | 
| @@ -658,18 +680,29 @@ module ActiveRecord | |
| 658 680 | 
             
                  # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
         | 
| 659 681 | 
             
                  def remove_references(*args, **options)
         | 
| 660 682 | 
             
                    args.each do |ref_name|
         | 
| 661 | 
            -
                      @base.remove_reference(name, ref_name, options)
         | 
| 683 | 
            +
                      @base.remove_reference(name, ref_name, **options)
         | 
| 662 684 | 
             
                    end
         | 
| 663 685 | 
             
                  end
         | 
| 664 686 | 
             
                  alias :remove_belongs_to :remove_references
         | 
| 665 687 |  | 
| 666 | 
            -
                  # Adds a foreign key.
         | 
| 688 | 
            +
                  # Adds a foreign key to the table using a supplied table name.
         | 
| 667 689 | 
             
                  #
         | 
| 668 690 | 
             
                  #  t.foreign_key(:authors)
         | 
| 691 | 
            +
                  #  t.foreign_key(:authors, column: :author_id, primary_key: "id")
         | 
| 669 692 | 
             
                  #
         | 
| 670 693 | 
             
                  # See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
         | 
| 671 | 
            -
                  def foreign_key(*args)
         | 
| 672 | 
            -
                    @base.add_foreign_key(name, *args)
         | 
| 694 | 
            +
                  def foreign_key(*args, **options)
         | 
| 695 | 
            +
                    @base.add_foreign_key(name, *args, **options)
         | 
| 696 | 
            +
                  end
         | 
| 697 | 
            +
             | 
| 698 | 
            +
                  # Removes the given foreign key from the table.
         | 
| 699 | 
            +
                  #
         | 
| 700 | 
            +
                  #  t.remove_foreign_key(:authors)
         | 
| 701 | 
            +
                  #  t.remove_foreign_key(column: :author_id)
         | 
| 702 | 
            +
                  #
         | 
| 703 | 
            +
                  # See {connection.remove_foreign_key}[rdoc-ref:SchemaStatements#remove_foreign_key]
         | 
| 704 | 
            +
                  def remove_foreign_key(*args, **options)
         | 
| 705 | 
            +
                    @base.remove_foreign_key(name, *args, **options)
         | 
| 673 706 | 
             
                  end
         | 
| 674 707 |  | 
| 675 708 | 
             
                  # Checks to see if a foreign key exists.
         | 
| @@ -677,8 +710,8 @@ module ActiveRecord | |
| 677 710 | 
             
                  #  t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
         | 
| 678 711 | 
             
                  #
         | 
| 679 712 | 
             
                  # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
         | 
| 680 | 
            -
                  def foreign_key_exists?(*args)
         | 
| 681 | 
            -
                    @base.foreign_key_exists?(name, *args)
         | 
| 713 | 
            +
                  def foreign_key_exists?(*args, **options)
         | 
| 714 | 
            +
                    @base.foreign_key_exists?(name, *args, **options)
         | 
| 682 715 | 
             
                  end
         | 
| 683 716 | 
             
                end
         | 
| 684 717 | 
             
              end
         | 
| @@ -1,7 +1,5 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require "active_support/core_ext/hash/compact"
         | 
| 4 | 
            -
             | 
| 5 3 | 
             
            module ActiveRecord
         | 
| 6 4 | 
             
              module ConnectionAdapters # :nodoc:
         | 
| 7 5 | 
             
                class SchemaDumper < SchemaDumper # :nodoc:
         | 
| @@ -17,7 +15,7 @@ module ActiveRecord | |
| 17 15 | 
             
                    def column_spec_for_primary_key(column)
         | 
| 18 16 | 
             
                      return {} if default_primary_key?(column)
         | 
| 19 17 | 
             
                      spec = { id: schema_type(column).inspect }
         | 
| 20 | 
            -
                      spec.merge!(prepare_column_options(column).except!(:null))
         | 
| 18 | 
            +
                      spec.merge!(prepare_column_options(column).except!(:null, :comment))
         | 
| 21 19 | 
             
                      spec[:default] ||= "nil" if explicit_primary_key_default?(column)
         | 
| 22 20 | 
             
                      spec
         | 
| 23 21 | 
             
                    end
         |