activerecord-sqlserver-adapter 5.0.8 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/BACKERS.md +32 -0
- data/CHANGELOG.md +3 -111
- data/RAILS5-TODO.md +21 -1
- data/README.md +7 -3
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +1 -1
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +10 -14
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +21 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +69 -51
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +15 -7
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +5 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +29 -18
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +2 -2
- data/lib/arel/visitors/sqlserver.rb +2 -1
- data/test/cases/adapter_test_sqlserver.rb +8 -12
- data/test/cases/coerced_tests.rb +86 -11
- data/test/cases/column_test_sqlserver.rb +1 -1
- data/test/cases/helper_sqlserver.rb +5 -0
- data/test/cases/pessimistic_locking_test_sqlserver.rb +0 -11
- data/test/cases/schema_dumper_test_sqlserver.rb +10 -10
- data/test/schema/sqlserver_specific_schema.rb +1 -1
- data/test/support/sql_counter_sqlserver.rb +1 -1
- metadata +6 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 13700d5c59ccddfde7189f1bf0dfac4bbd276777
         | 
| 4 | 
            +
              data.tar.gz: e9cafb310dfe9904c39dbf77ccc5bb86687f231a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2cbb63f122e3ad2657532e7649c33728a0790f945043a12afdb078d171122970636a81dfa621485aa6a8abe7d30b9ab3892d2fef76fefd0a7ed6019fbda543dd
         | 
| 7 | 
            +
              data.tar.gz: 220bc1f5a936151978885af18c38f7a25d7e684f0d7199c64d21d30922c4b33b8312e2a0db924f59d3040b0b147bbc6fa4dc564b5e1fbe6bb190daa522b322b4
         | 
    
        data/BACKERS.md
    ADDED
    
    | @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            # Backers
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            You can join in supporting TinyTDS and the Rails SQL Server Adapter development by [pledging on Patreon](https://www.patreon.com/metaskills)! Backers in the same pledge level appear in the order of pledge date.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ### $2000
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611218)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
             | 
| 10 | 
            +
            ### $500
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611209)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            ### $250
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611199)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| 20 | 
            +
            ### $100
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611196)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
            ### $50+
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611186)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             | 
| 30 | 
            +
            ### $10+
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611149)
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,120 +1,12 @@ | |
| 1 | 
            -
            ## v5.0 | 
| 2 | 
            -
             | 
| 3 | 
            -
            * Memorized SQL Server Version to prevent a flood of SELECT @@version queries. Fixes #632
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            ## v5.0.7
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            * Add `WITH NO_INFOMSGS` to `user_options` method. Fixes #580
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
            ## v5.0.6
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            #### Fixed
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            * Performance w/inserts. Check binds & use schema cache for id inserts.
         | 
| 15 | 
            -
              Fixes #572. Thanks @noelr.
         | 
| 16 | 
            -
            * Add smalldatetime type for migrations. Fixes #507
         | 
| 17 | 
            -
             | 
| 18 | 
            -
            #### Changed
         | 
| 19 | 
            -
             | 
| 20 | 
            -
            * Misc index enhancements or testing. Fixes #570
         | 
| 21 | 
            -
              Enable `supports_index_sort_order?`, test `supports_partial_index?`, test how expression indexes work.
         | 
| 22 | 
            -
             | 
| 23 | 
            -
            #### Added
         | 
| 24 | 
            -
             | 
| 25 | 
            -
            * New `primary_key_nonclustered` type for easy In-Memory table creation.
         | 
| 26 | 
            -
            * Examples for an In-Memory table.
         | 
| 27 | 
            -
             | 
| 28 | 
            -
            ```ruby
         | 
| 29 | 
            -
            create_table :in_memory_table, id: false,
         | 
| 30 | 
            -
                         options: 'WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)' do |t|
         | 
| 31 | 
            -
              t.primary_key_nonclustered :id
         | 
| 32 | 
            -
              t.string :name
         | 
| 33 | 
            -
              t.timestamps
         | 
| 34 | 
            -
            end
         | 
| 35 | 
            -
            ```
         | 
| 36 | 
            -
             | 
| 37 | 
            -
            * Enable supports_json? Fixes #577.
         | 
| 38 | 
            -
             | 
| 39 | 
            -
            ```ruby
         | 
| 40 | 
            -
            create_table :users do |t|
         | 
| 41 | 
            -
              t.string :name, :email
         | 
| 42 | 
            -
              t.json :data # Creates a nvarchar(max) column.
         | 
| 43 | 
            -
             end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
            class Users < ActiveRecord::Base
         | 
| 46 | 
            -
              attribute :data, ActiveRecord::Type::SQLServer::Json.new
         | 
| 47 | 
            -
            end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
            User.create! name: 'Ken Collins', data: { 'admin' => true, 'foo' => 'bar' }
         | 
| 50 | 
            -
             | 
| 51 | 
            -
            admin = User.where("JSON_VALUE(data, '$.admin') = CAST(1 AS BIT)").first
         | 
| 52 | 
            -
            admin.data['foo'] # => "bar"
         | 
| 53 | 
            -
            ```
         | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
            ## v5.0.5
         | 
| 57 | 
            -
             | 
| 58 | 
            -
            #### Changed
         | 
| 59 | 
            -
             | 
| 60 | 
            -
            * Add TinyTDS as a runtime dependency.
         | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
            ## v5.0.4
         | 
| 1 | 
            +
            ## v5.1.0
         | 
| 64 2 |  | 
| 65 3 | 
             
            #### Fixed
         | 
| 66 4 |  | 
| 67 | 
            -
            * Allow `datetimeoffset` to be used in migrations and represented in schema.
         | 
| 68 | 
            -
            * Using transactions and resetting isolation level correctly when `READ_COMMITTED_SNAPSHOT` is set to `ON` Fixes #520
         | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
            ## v5.0.3
         | 
| 72 | 
            -
             | 
| 73 | 
            -
            #### Changed
         | 
| 74 | 
            -
             | 
| 75 | 
            -
            * Reduce view information reflection to per table vs. column. Fixes #552
         | 
| 76 | 
            -
            * The `user_options` parsing. Works for hash/array. Fixes #535
         | 
| 77 | 
            -
            * Pass the `:contained` option to TinyTDS. Fixes #527
         | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
            ## v5.0.2
         | 
| 81 | 
            -
             | 
| 82 | 
            -
            #### Fixed
         | 
| 83 | 
            -
             | 
| 84 | 
            -
            * Filter table constraints with matching table schema to column. Fixes #478
         | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
            ## v5.0.1
         | 
| 88 | 
            -
             | 
| 89 5 | 
             
            #### Changed
         | 
| 90 6 |  | 
| 91 | 
            -
            *  | 
| 92 | 
            -
             | 
| 93 | 
            -
            #### Fixed
         | 
| 94 | 
            -
             | 
| 95 | 
            -
            * Support 2014, 2012 drop table statement.
         | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
            ## v5.0.0
         | 
| 7 | 
            +
            * The `drop_table` with force cascade option now mimics in via pure SQL for us.
         | 
| 99 8 |  | 
| 100 9 | 
             
            #### Added
         | 
| 101 10 |  | 
| 102 | 
            -
            * Support  | 
| 103 | 
            -
            * Support for `unprepared_statement` blocks on the connection.
         | 
| 104 | 
            -
             | 
| 105 | 
            -
            #### Changed
         | 
| 106 | 
            -
             | 
| 107 | 
            -
            * Major refactoring of all type objects. Especially time types.
         | 
| 108 | 
            -
             | 
| 109 | 
            -
            #### Deprecated
         | 
| 110 | 
            -
             | 
| 111 | 
            -
            * Support for a handful of standard Rails deprecations in 5-0-stable suite.
         | 
| 112 | 
            -
             | 
| 113 | 
            -
            #### Removed
         | 
| 114 | 
            -
             | 
| 115 | 
            -
            * ODBC connection mode. Not been maintained since Rails 4.0.
         | 
| 116 | 
            -
            * View table name detection in `with_identity_insert_enabled` method for fixtures. Perf hit.
         | 
| 117 | 
            -
             | 
| 118 | 
            -
            #### Fixed
         | 
| 11 | 
            +
            * Support MismatchedForeignKey exception.
         | 
| 119 12 |  | 
| 120 | 
            -
            * Do not output column collation in schema when same as database.
         | 
    
        data/RAILS5-TODO.md
    CHANGED
    
    | @@ -2,4 +2,24 @@ | |
| 2 2 | 
             
            ## Rails v5.1
         | 
| 3 3 |  | 
| 4 4 | 
             
            * BIGINT PK support. https://github.com/rails/rails/pull/26266
         | 
| 5 | 
            -
             | 
| 5 | 
            +
            * Raise `ActiveRecord::NotNullViolation` when a record cannot be inserted
         | 
| 6 | 
            +
              or updated because it would violate a not null constraint.
         | 
| 7 | 
            +
            * Raise `ActiveRecord::RangeError` when values that executed are out of range.
         | 
| 8 | 
            +
            * Allow passing extra flags to `db:structure:load` and `db:structure:dump`
         | 
| 9 | 
            +
              Introduces `ActiveRecord::Tasks::DatabaseTasks.structure_(load|dump)_flags` to customize the
         | 
| 10 | 
            +
              eventual commands run against the database, e.g. mysqldump/pg_dump.
         | 
| 11 | 
            +
            * Set `:time` as a timezone aware type and remove deprecation when
         | 
| 12 | 
            +
              `config.active_record.time_zone_aware_types` is not explicitly set.
         | 
| 13 | 
            +
            * Remove deprecated support to passing a column to `#quote`.
         | 
| 14 | 
            +
            * `#tables` and `#table_exists?` return only tables and not views.
         | 
| 15 | 
            +
              All the deprecations on those methods were removed.
         | 
| 16 | 
            +
            * Remove deprecated `original_exception` argument in `ActiveRecord::StatementInvalid#initialize`
         | 
| 17 | 
            +
              and `ActiveRecord::StatementInvalid#original_exception`.
         | 
| 18 | 
            +
            * Remove deprecated tasks: `db:test:clone`, `db:test:clone_schema`, `db:test:clone_structure`.
         | 
| 19 | 
            +
            * Make `table_name=` reset current statement cache,
         | 
| 20 | 
            +
              so queries are not run against the previous table name.
         | 
| 21 | 
            +
            * Deprecate using `#quoted_id` in quoting.
         | 
| 22 | 
            +
            * Deprecate `supports_migrations?` on connection adapters.
         | 
| 23 | 
            +
            * Dig moving `Column#sqlserver_options` to `sql_type_metadata` delegate.
         | 
| 24 | 
            +
            * Should we do like PG and add `options[:collation]` before `#add_column_options!`?
         | 
| 25 | 
            +
            * Translated exceptions: `SerializationFailure` and `RangeError`.
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,5 +1,3 @@ | |
| 1 | 
            -
            [](https://gratipay.com/metaskills/)
         | 
| 2 | 
            -
             | 
| 3 1 | 
             
            # ActiveRecord SQL Server Adapter. For SQL Server 2012 And Higher.
         | 
| 4 2 |  | 
| 5 3 | 
             
            * [](https://travis-ci.org/rails-sqlserver/activerecord-sqlserver-adapter) - TravisCI
         | 
| @@ -9,6 +7,12 @@ | |
| 9 7 | 
             
            * [](https://dependencyci.com/github/rails-sqlserver/activerecord-sqlserver-adapter) - Dependency Status
         | 
| 10 8 | 
             
            * [](https://gitter.im/rails-sqlserver/activerecord-sqlserver-adapter) - Community
         | 
| 11 9 |  | 
| 10 | 
            +
            ## Supporting TinyTDS/Adapter
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            Both TinyTDS and the Rails SQL Server Adapter are MIT-licensed open source projects. Its ongoing development is made possible thanks to the support by these awesome [backers](https://github.com/rails-sqlserver/tiny_tds/blob/master/BACKERS.md). If you'd like to join them, check out our [Patreon Campaign](https://www.patreon.com/metaskills).
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            ## About The Adapter
         | 
| 12 16 |  | 
| 13 17 | 
             
            The SQL Server adapter for ActiveRecord v5.0 using SQL Server 2012 or higher.
         | 
| 14 18 |  | 
| @@ -129,7 +133,7 @@ If you would like to contribute a feature or bugfix, thanks! To make sure your f | |
| 129 133 | 
             
            Many many people have contributed. If you do not see your name here and it should be let us know. Also, many thanks go out to those that have pledged financial contributions.
         | 
| 130 134 |  | 
| 131 135 |  | 
| 132 | 
            -
            ##  | 
| 136 | 
            +
            ## Contributors
         | 
| 133 137 |  | 
| 134 138 | 
             
            Up-to-date list of contributors: http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/contributors
         | 
| 135 139 |  | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            5.0 | 
| 1 | 
            +
            5.1.0
         | 
| @@ -16,6 +16,6 @@ Gem::Specification.new do |spec| | |
| 16 16 | 
             
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
| 17 17 | 
             
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         | 
| 18 18 | 
             
              spec.require_paths = ['lib']
         | 
| 19 | 
            -
              spec.add_dependency 'activerecord', '~> 5. | 
| 19 | 
            +
              spec.add_dependency 'activerecord', '~> 5.1.0'
         | 
| 20 20 | 
             
              spec.add_dependency 'tiny_tds'
         | 
| 21 21 | 
             
            end
         | 
| @@ -3,10 +3,6 @@ module ActiveRecord | |
| 3 3 | 
             
                module SQLServer
         | 
| 4 4 | 
             
                  module DatabaseStatements
         | 
| 5 5 |  | 
| 6 | 
            -
                    def select_rows(sql, name = nil, binds = [])
         | 
| 7 | 
            -
                      sp_executesql sql, name, binds, fetch: :rows
         | 
| 8 | 
            -
                    end
         | 
| 9 | 
            -
             | 
| 10 6 | 
             
                    def execute(sql, name = nil)
         | 
| 11 7 | 
             
                      if id_insert_table_name = query_requires_identity_insert?(sql)
         | 
| 12 8 | 
             
                        with_identity_insert_enabled(id_insert_table_name) { do_execute(sql, name) }
         | 
| @@ -19,22 +15,22 @@ module ActiveRecord | |
| 19 15 | 
             
                      sp_executesql(sql, name, binds, prepare: prepare)
         | 
| 20 16 | 
             
                    end
         | 
| 21 17 |  | 
| 22 | 
            -
                    def exec_insert(sql, name, binds, pk = nil, _sequence_name = nil)
         | 
| 18 | 
            +
                    def exec_insert(sql, name = nil, binds = [], pk = nil, _sequence_name = nil)
         | 
| 23 19 | 
             
                      if id_insert_table_name = exec_insert_requires_identity?(sql, pk, binds)
         | 
| 24 | 
            -
                        with_identity_insert_enabled(id_insert_table_name) {  | 
| 20 | 
            +
                        with_identity_insert_enabled(id_insert_table_name) { super(sql, name, binds, pk) }
         | 
| 25 21 | 
             
                      else
         | 
| 26 | 
            -
                         | 
| 22 | 
            +
                        super(sql, name, binds, pk)
         | 
| 27 23 | 
             
                      end
         | 
| 28 24 | 
             
                    end
         | 
| 29 25 |  | 
| 30 26 | 
             
                    def exec_delete(sql, name, binds)
         | 
| 31 | 
            -
                      sql << '; SELECT @@ROWCOUNT AS AffectedRows'
         | 
| 32 | 
            -
                      super.rows.first.first
         | 
| 27 | 
            +
                      sql = sql.dup << '; SELECT @@ROWCOUNT AS AffectedRows'
         | 
| 28 | 
            +
                      super(sql, name, binds).rows.first.first
         | 
| 33 29 | 
             
                    end
         | 
| 34 30 |  | 
| 35 31 | 
             
                    def exec_update(sql, name, binds)
         | 
| 36 | 
            -
                      sql << '; SELECT @@ROWCOUNT AS AffectedRows'
         | 
| 37 | 
            -
                      super.rows.first.first
         | 
| 32 | 
            +
                      sql = sql.dup << '; SELECT @@ROWCOUNT AS AffectedRows'
         | 
| 33 | 
            +
                      super(sql, name, binds).rows.first.first
         | 
| 38 34 | 
             
                    end
         | 
| 39 35 |  | 
| 40 36 | 
             
                    def supports_statement_cache?
         | 
| @@ -80,7 +76,7 @@ module ActiveRecord | |
| 80 76 | 
             
                    end
         | 
| 81 77 |  | 
| 82 78 | 
             
                    def case_sensitive_comparison(table, attribute, column, value)
         | 
| 83 | 
            -
                      if  | 
| 79 | 
            +
                      if column.collation && !column.case_sensitive?
         | 
| 84 80 | 
             
                        table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
         | 
| 85 81 | 
             
                      else
         | 
| 86 82 | 
             
                        super
         | 
| @@ -198,7 +194,7 @@ module ActiveRecord | |
| 198 194 | 
             
                      end
         | 
| 199 195 | 
             
                      sql = if pk && self.class.use_output_inserted && !database_prefix_remote_server?
         | 
| 200 196 | 
             
                              quoted_pk = SQLServer::Utils.extract_identifiers(pk).quoted
         | 
| 201 | 
            -
                              sql.insert sql.index(/ (DEFAULT )?VALUES/), " OUTPUT INSERTED.#{quoted_pk}"
         | 
| 197 | 
            +
                              sql.dup.insert sql.index(/ (DEFAULT )?VALUES/), " OUTPUT INSERTED.#{quoted_pk}"
         | 
| 202 198 | 
             
                            else
         | 
| 203 199 | 
             
                              "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"
         | 
| 204 200 | 
             
                            end
         | 
| @@ -261,7 +257,7 @@ module ActiveRecord | |
| 261 257 | 
             
                      if name == 'EXPLAIN'
         | 
| 262 258 | 
             
                        params.each.with_index do |param, index|
         | 
| 263 259 | 
             
                          substitute_at_finder = /(@#{index})(?=(?:[^']|'[^']*')*$)/ # Finds unquoted @n values.
         | 
| 264 | 
            -
                          sql.sub | 
| 260 | 
            +
                          sql = sql.sub substitute_at_finder, param.to_s
         | 
| 265 261 | 
             
                        end
         | 
| 266 262 | 
             
                      else
         | 
| 267 263 | 
             
                        types = quote(types.join(', '))
         | 
| @@ -16,6 +16,20 @@ module ActiveRecord | |
| 16 16 | 
             
                      end
         | 
| 17 17 | 
             
                    end
         | 
| 18 18 |  | 
| 19 | 
            +
                    def add_column_options!(sql, options)
         | 
| 20 | 
            +
                      sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
         | 
| 21 | 
            +
                      if options[:null] == false
         | 
| 22 | 
            +
                        sql << " NOT NULL"
         | 
| 23 | 
            +
                      end
         | 
| 24 | 
            +
                      if options[:is_identity] == true
         | 
| 25 | 
            +
                        sql << " IDENTITY(1,1)"
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
                      if options[:primary_key] == true
         | 
| 28 | 
            +
                        sql << " PRIMARY KEY"
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
                      sql
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 19 33 | 
             
                    def action_sql(action, dependency)
         | 
| 20 34 | 
             
                      case dependency
         | 
| 21 35 | 
             
                      when :restrict
         | 
| @@ -28,6 +42,14 @@ module ActiveRecord | |
| 28 42 | 
             
                      end
         | 
| 29 43 | 
             
                    end
         | 
| 30 44 |  | 
| 45 | 
            +
                    def options_include_default?(options)
         | 
| 46 | 
            +
                      super || options_primary_key_with_nil_default?(options)
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    def options_primary_key_with_nil_default?(options)
         | 
| 50 | 
            +
                      options[:primary_key] && options.include?(:default) && options[:default].nil?
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 31 53 | 
             
                  end
         | 
| 32 54 | 
             
                end
         | 
| 33 55 | 
             
              end
         | 
| @@ -3,13 +3,34 @@ module ActiveRecord | |
| 3 3 | 
             
                module SQLServer
         | 
| 4 4 | 
             
                  module SchemaDumper
         | 
| 5 5 |  | 
| 6 | 
            +
                    SQLSEVER_NO_LIMIT_TYPES = [
         | 
| 7 | 
            +
                      'text',
         | 
| 8 | 
            +
                      'ntext',
         | 
| 9 | 
            +
                      'varchar(max)',
         | 
| 10 | 
            +
                      'nvarchar(max)',
         | 
| 11 | 
            +
                      'varbinary(max)'
         | 
| 12 | 
            +
                    ].freeze
         | 
| 13 | 
            +
             | 
| 6 14 | 
             
                    private
         | 
| 7 15 |  | 
| 16 | 
            +
                    def explicit_primary_key_default?(column)
         | 
| 17 | 
            +
                      column.is_primary? && !column.is_identity?
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def schema_limit(column)
         | 
| 21 | 
            +
                      return if SQLSEVER_NO_LIMIT_TYPES.include?(column.sql_type)
         | 
| 22 | 
            +
                      super
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 8 25 | 
             
                    def schema_collation(column)
         | 
| 9 26 | 
             
                      return unless column.collation
         | 
| 10 27 | 
             
                      column.collation if column.collation != collation
         | 
| 11 28 | 
             
                    end
         | 
| 12 29 |  | 
| 30 | 
            +
                    def default_primary_key?(column)
         | 
| 31 | 
            +
                      super && column.is_primary? && column.is_identity?
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 13 34 | 
             
                  end
         | 
| 14 35 | 
             
                end
         | 
| 15 36 | 
             
              end
         | 
| @@ -7,35 +7,6 @@ module ActiveRecord | |
| 7 7 | 
             
                      @native_database_types ||= initialize_native_database_types.freeze
         | 
| 8 8 | 
             
                    end
         | 
| 9 9 |  | 
| 10 | 
            -
                    def tables(name = nil)
         | 
| 11 | 
            -
                      ActiveSupport::Deprecation.warn 'Passing arguments to #tables is deprecated without replacement.' if name
         | 
| 12 | 
            -
                      tables_sql('BASE TABLE')
         | 
| 13 | 
            -
                    end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                    def table_exists?(table_name)
         | 
| 16 | 
            -
                      ActiveSupport::Deprecation.warn(<<-MSG.squish)
         | 
| 17 | 
            -
                        #table_exists? currently checks both tables and views.
         | 
| 18 | 
            -
                        This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
         | 
| 19 | 
            -
                        Use #data_source_exists? instead.
         | 
| 20 | 
            -
                      MSG
         | 
| 21 | 
            -
                      data_source_exists?(table_name)
         | 
| 22 | 
            -
                    end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    def data_source_exists?(table_name)
         | 
| 25 | 
            -
                      return false if table_name.blank?
         | 
| 26 | 
            -
                      unquoted_table_name = SQLServer::Utils.extract_identifiers(table_name).object
         | 
| 27 | 
            -
                      super(unquoted_table_name)
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                    def views
         | 
| 31 | 
            -
                      tables_sql('VIEW')
         | 
| 32 | 
            -
                    end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                    def view_exists?(table_name)
         | 
| 35 | 
            -
                      identifier = SQLServer::Utils.extract_identifiers(table_name)
         | 
| 36 | 
            -
                      super(identifier.object)
         | 
| 37 | 
            -
                    end
         | 
| 38 | 
            -
             | 
| 39 10 | 
             
                    def create_table(table_name, comment: nil, **options)
         | 
| 40 11 | 
             
                      res = super
         | 
| 41 12 | 
             
                      clear_cache!
         | 
| @@ -43,6 +14,17 @@ module ActiveRecord | |
| 43 14 | 
             
                    end
         | 
| 44 15 |  | 
| 45 16 | 
             
                    def drop_table(table_name, options = {})
         | 
| 17 | 
            +
                      # Mimic CASCADE option as best we can.
         | 
| 18 | 
            +
                      if options[:force] == :cascade
         | 
| 19 | 
            +
                        execute_procedure(:sp_fkeys, pktable_name: table_name).each do |fkdata|
         | 
| 20 | 
            +
                          fktable = fkdata['FKTABLE_NAME']
         | 
| 21 | 
            +
                          fkcolmn = fkdata['FKCOLUMN_NAME']
         | 
| 22 | 
            +
                          pktable = fkdata['PKTABLE_NAME']
         | 
| 23 | 
            +
                          pkcolmn = fkdata['PKCOLUMN_NAME']
         | 
| 24 | 
            +
                          remove_foreign_key fktable, name: fkdata['FK_NAME']
         | 
| 25 | 
            +
                          do_execute "DELETE FROM #{quote_table_name(fktable)} WHERE #{quote_column_name(fkcolmn)} IN ( SELECT #{quote_column_name(pkcolmn)} FROM #{quote_table_name(pktable)} )"
         | 
| 26 | 
            +
                        end
         | 
| 27 | 
            +
                      end
         | 
| 46 28 | 
             
                      if options[:if_exists] && @version_year != 2016
         | 
| 47 29 | 
             
                        execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #{quote(table_name)}) DROP TABLE #{quote_table_name(table_name)}"
         | 
| 48 30 | 
             
                      else
         | 
| @@ -103,10 +85,34 @@ module ActiveRecord | |
| 103 85 | 
             
                    end
         | 
| 104 86 |  | 
| 105 87 | 
             
                    def primary_keys(table_name)
         | 
| 106 | 
            -
                      primaries =  | 
| 88 | 
            +
                      primaries = primary_keys_select(table_name)
         | 
| 107 89 | 
             
                      primaries.present? ? primaries : identity_columns(table_name).map(&:name)
         | 
| 108 90 | 
             
                    end
         | 
| 109 91 |  | 
| 92 | 
            +
                    def primary_keys_select(table_name)
         | 
| 93 | 
            +
                      identifier = database_prefix_identifier(table_name)
         | 
| 94 | 
            +
                      database = identifier.fully_qualified_database_quoted
         | 
| 95 | 
            +
                      sql = %{
         | 
| 96 | 
            +
                        SELECT KCU.COLUMN_NAME AS [name]
         | 
| 97 | 
            +
                        FROM #{database}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU
         | 
| 98 | 
            +
                        LEFT OUTER JOIN #{database}.INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
         | 
| 99 | 
            +
                          ON KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
         | 
| 100 | 
            +
                          AND KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
         | 
| 101 | 
            +
                          AND KCU.CONSTRAINT_CATALOG = TC.CONSTRAINT_CATALOG
         | 
| 102 | 
            +
                          AND KCU.CONSTRAINT_SCHEMA = TC.CONSTRAINT_SCHEMA
         | 
| 103 | 
            +
                          AND TC.CONSTRAINT_TYPE = N'PRIMARY KEY'
         | 
| 104 | 
            +
                        WHERE KCU.TABLE_NAME = #{prepared_statements ? '@0' : quote(identifier.object)}
         | 
| 105 | 
            +
                        AND KCU.TABLE_SCHEMA = #{identifier.schema.blank? ? 'schema_name()' : (prepared_statements ? '@1' : quote(identifier.schema))}
         | 
| 106 | 
            +
                        AND TC.CONSTRAINT_TYPE = N'PRIMARY KEY'
         | 
| 107 | 
            +
                        ORDER BY KCU.ORDINAL_POSITION ASC
         | 
| 108 | 
            +
                      }.gsub(/[[:space:]]/, ' ')
         | 
| 109 | 
            +
                      binds = []
         | 
| 110 | 
            +
                      nv128 = SQLServer::Type::UnicodeVarchar.new limit: 128
         | 
| 111 | 
            +
                      binds << Relation::QueryAttribute.new('TABLE_NAME', identifier.object, nv128)
         | 
| 112 | 
            +
                      binds << Relation::QueryAttribute.new('TABLE_SCHEMA', identifier.schema, nv128) unless identifier.schema.blank?
         | 
| 113 | 
            +
                      sp_executesql(sql, 'SCHEMA', binds).map { |r| r['name'] }
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
             | 
| 110 116 | 
             
                    def rename_table(table_name, new_name)
         | 
| 111 117 | 
             
                      do_execute "EXEC sp_rename '#{table_name}', '#{new_name}'"
         | 
| 112 118 | 
             
                      rename_table_indexes(table_name, new_name)
         | 
| @@ -130,9 +136,11 @@ module ActiveRecord | |
| 130 136 | 
             
                        remove_indexes(table_name, column_name)
         | 
| 131 137 | 
             
                      end
         | 
| 132 138 | 
             
                      sql_commands << "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_expression(options[:default], column_object)} WHERE #{quote_column_name(column_name)} IS NULL" if !options[:null].nil? && options[:null] == false && !options[:default].nil?
         | 
| 133 | 
            -
                      sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
         | 
| 134 | 
            -
                      sql_commands | 
| 135 | 
            -
                      if  | 
| 139 | 
            +
                      sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, limit: options[:limit], precision: options[:precision], scale: options[:scale])}"
         | 
| 140 | 
            +
                      sql_commands.last << ' NOT NULL' if !options[:null].nil? && options[:null] == false
         | 
| 141 | 
            +
                      if options.key?(:default) && default_constraint_name(table_name, column_name).present?
         | 
| 142 | 
            +
                        change_column_default(table_name, column_name, options[:default])
         | 
| 143 | 
            +
                      elsif options_include_default?(options)
         | 
| 136 144 | 
             
                        sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(options[:default], column_object)} FOR #{quote_column_name(column_name)}"
         | 
| 137 145 | 
             
                      end
         | 
| 138 146 | 
             
                      # Add any removed indexes back
         | 
| @@ -140,6 +148,7 @@ module ActiveRecord | |
| 140 148 | 
             
                        sql_commands << "CREATE INDEX #{quote_table_name(index.name)} ON #{quote_table_name(table_name)} (#{index.columns.map { |c| quote_column_name(c) }.join(', ')})"
         | 
| 141 149 | 
             
                      end
         | 
| 142 150 | 
             
                      sql_commands.each { |c| do_execute(c) }
         | 
| 151 | 
            +
                      clear_cache!
         | 
| 143 152 | 
             
                    end
         | 
| 144 153 |  | 
| 145 154 | 
             
                    def change_column_default(table_name, column_name, default_or_changes)
         | 
| @@ -194,7 +203,7 @@ module ActiveRecord | |
| 194 203 | 
             
                      end
         | 
| 195 204 | 
             
                    end
         | 
| 196 205 |  | 
| 197 | 
            -
                    def type_to_sql(type, limit  | 
| 206 | 
            +
                    def type_to_sql(type, limit: nil, precision: nil, scale: nil, **)
         | 
| 198 207 | 
             
                      type_limitable = %w(string integer float char nchar varchar nvarchar).include?(type.to_s)
         | 
| 199 208 | 
             
                      limit = nil unless type_limitable
         | 
| 200 209 | 
             
                      case type.to_s
         | 
| @@ -240,19 +249,40 @@ module ActiveRecord | |
| 240 249 | 
             
                      if !allow_null.nil? && allow_null == false && !default.nil?
         | 
| 241 250 | 
             
                        do_execute("UPDATE #{table_id} SET #{column_id}=#{quote(default)} WHERE #{column_id} IS NULL")
         | 
| 242 251 | 
             
                      end
         | 
| 243 | 
            -
                      sql = "ALTER TABLE #{table_id} ALTER COLUMN #{column_id} #{type_to_sql column.type, column.limit, column.precision, column.scale}"
         | 
| 252 | 
            +
                      sql = "ALTER TABLE #{table_id} ALTER COLUMN #{column_id} #{type_to_sql column.type, limit: column.limit, precision: column.precision, scale: column.scale}"
         | 
| 244 253 | 
             
                      sql << ' NOT NULL' if !allow_null.nil? && allow_null == false
         | 
| 245 254 | 
             
                      do_execute sql
         | 
| 246 255 | 
             
                    end
         | 
| 247 256 |  | 
| 257 | 
            +
                    private
         | 
| 248 258 |  | 
| 249 | 
            -
                     | 
| 259 | 
            +
                    def data_source_sql(name = nil, type: nil)
         | 
| 260 | 
            +
                      scope = quoted_scope name, type: type
         | 
| 261 | 
            +
                      table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
         | 
| 262 | 
            +
                      sql = "SELECT #{table_name}"
         | 
| 263 | 
            +
                      sql << ' FROM INFORMATION_SCHEMA.TABLES'
         | 
| 264 | 
            +
                      sql << ' WHERE TABLE_CATALOG = DB_NAME()'
         | 
| 265 | 
            +
                      sql << " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
         | 
| 266 | 
            +
                      sql << " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
         | 
| 267 | 
            +
                      sql << " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
         | 
| 268 | 
            +
                      sql << " ORDER BY #{table_name}"
         | 
| 269 | 
            +
                      sql
         | 
| 270 | 
            +
                    end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                    def quoted_scope(name = nil, type: nil)
         | 
| 273 | 
            +
                      identifier = SQLServer::Utils.extract_identifiers(name)
         | 
| 274 | 
            +
                      {}.tap do |scope|
         | 
| 275 | 
            +
                        scope[:schema] = identifier.schema || 'dbo'
         | 
| 276 | 
            +
                        scope[:name] = identifier.object if identifier.object
         | 
| 277 | 
            +
                        scope[:type] = type if type
         | 
| 278 | 
            +
                      end
         | 
| 279 | 
            +
                    end
         | 
| 250 280 |  | 
| 251 281 | 
             
                    # === SQLServer Specific ======================================== #
         | 
| 252 282 |  | 
| 253 283 | 
             
                    def initialize_native_database_types
         | 
| 254 284 | 
             
                      {
         | 
| 255 | 
            -
                        primary_key: ' | 
| 285 | 
            +
                        primary_key: 'bigint NOT NULL IDENTITY(1,1) PRIMARY KEY',
         | 
| 256 286 | 
             
                        primary_key_nonclustered: 'int NOT NULL IDENTITY(1,1) PRIMARY KEY NONCLUSTERED',
         | 
| 257 287 | 
             
                        integer: { name: 'int', limit: 4 },
         | 
| 258 288 | 
             
                        bigint: { name: 'bigint' },
         | 
| @@ -286,18 +316,8 @@ module ActiveRecord | |
| 286 316 | 
             
                      }
         | 
| 287 317 | 
             
                    end
         | 
| 288 318 |  | 
| 289 | 
            -
                    def tables_sql(type)
         | 
| 290 | 
            -
                      tn  = lowercase_schema_reflection_sql 'TABLE_NAME'
         | 
| 291 | 
            -
                      sql = "SELECT #{tn} FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = '#{type}' ORDER BY TABLE_NAME"
         | 
| 292 | 
            -
                      select_values sql, 'SCHEMA'
         | 
| 293 | 
            -
                    end
         | 
| 294 | 
            -
             | 
| 295 319 | 
             
                    def column_definitions(table_name)
         | 
| 296 | 
            -
                      identifier | 
| 297 | 
            -
                        SQLServer::Utils.extract_identifiers("#{database_prefix}#{table_name}")
         | 
| 298 | 
            -
                      else
         | 
| 299 | 
            -
                        SQLServer::Utils.extract_identifiers(table_name)
         | 
| 300 | 
            -
                      end
         | 
| 320 | 
            +
                      identifier  = database_prefix_identifier(table_name)
         | 
| 301 321 | 
             
                      database    = identifier.fully_qualified_database_quoted
         | 
| 302 322 | 
             
                      view_exists = view_exists?(table_name)
         | 
| 303 323 | 
             
                      view_tblnm  = view_table_name(table_name) if view_exists
         | 
| @@ -475,7 +495,7 @@ module ActiveRecord | |
| 475 495 | 
             
                      @view_information ||= {}
         | 
| 476 496 | 
             
                      @view_information[table_name] ||= begin
         | 
| 477 497 | 
             
                        identifier = SQLServer::Utils.extract_identifiers(table_name)
         | 
| 478 | 
            -
                        view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME =  | 
| 498 | 
            +
                        view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = #{quote(identifier.object)}", 'SCHEMA'
         | 
| 479 499 | 
             
                        if view_info
         | 
| 480 500 | 
             
                          view_info = view_info.with_indifferent_access
         | 
| 481 501 | 
             
                          if view_info[:VIEW_DEFINITION].blank? || view_info[:VIEW_DEFINITION].length == 4000
         | 
| @@ -498,8 +518,6 @@ module ActiveRecord | |
| 498 518 | 
             
                      match_data ? match_data[1] : column_name
         | 
| 499 519 | 
             
                    end
         | 
| 500 520 |  | 
| 501 | 
            -
                    private
         | 
| 502 | 
            -
             | 
| 503 521 | 
             
                    def create_table_definition(*args)
         | 
| 504 522 | 
             
                      SQLServer::TableDefinition.new(*args)
         | 
| 505 523 | 
             
                    end
         | 
| @@ -5,10 +5,13 @@ module ActiveRecord | |
| 5 5 | 
             
                  module ColumnMethods
         | 
| 6 6 |  | 
| 7 7 | 
             
                    def primary_key(name, type = :primary_key, **options)
         | 
| 8 | 
            -
                       | 
| 9 | 
            -
             | 
| 10 | 
            -
                       | 
| 11 | 
            -
             | 
| 8 | 
            +
                      if [:integer, :bigint].include?(type)
         | 
| 9 | 
            +
                        options[:is_identity] = true unless options.key?(:default)
         | 
| 10 | 
            +
                      elsif type == :uuid
         | 
| 11 | 
            +
                        options[:default] = options.fetch(:default, 'NEWID()')
         | 
| 12 | 
            +
                        options[:primary_key] = true
         | 
| 13 | 
            +
                      end
         | 
| 14 | 
            +
                      super
         | 
| 12 15 | 
             
                    end
         | 
| 13 16 |  | 
| 14 17 | 
             
                    def primary_key_nonclustered(*args, **options)
         | 
| @@ -98,9 +101,14 @@ module ActiveRecord | |
| 98 101 | 
             
                  class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
         | 
| 99 102 | 
             
                    include ColumnMethods
         | 
| 100 103 |  | 
| 101 | 
            -
                    def new_column_definition(name, type, options)
         | 
| 102 | 
            -
                       | 
| 103 | 
            -
                       | 
| 104 | 
            +
                    def new_column_definition(name, type, **options)
         | 
| 105 | 
            +
                      case type
         | 
| 106 | 
            +
                      when :datetime
         | 
| 107 | 
            +
                        type = :datetime2 if options[:precision]
         | 
| 108 | 
            +
                      when :primary_key
         | 
| 109 | 
            +
                        options[:is_identity] = true
         | 
| 110 | 
            +
                      end
         | 
| 111 | 
            +
                      super
         | 
| 104 112 | 
             
                    end
         | 
| 105 113 | 
             
                  end
         | 
| 106 114 |  | 
| @@ -73,14 +73,6 @@ module ActiveRecord | |
| 73 73 | 
             
                    SQLServer::SchemaCreation.new self
         | 
| 74 74 | 
             
                  end
         | 
| 75 75 |  | 
| 76 | 
            -
                  def supports_migrations?
         | 
| 77 | 
            -
                    true
         | 
| 78 | 
            -
                  end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                  def supports_primary_key?
         | 
| 81 | 
            -
                    true
         | 
| 82 | 
            -
                  end
         | 
| 83 | 
            -
             | 
| 84 76 | 
             
                  def supports_ddl_transactions?
         | 
| 85 77 | 
             
                    true
         | 
| 86 78 | 
             
                  end
         | 
| @@ -147,10 +139,10 @@ module ActiveRecord | |
| 147 139 |  | 
| 148 140 | 
             
                  def disable_referential_integrity
         | 
| 149 141 | 
             
                    tables = tables_with_referential_integrity
         | 
| 150 | 
            -
                    tables.each { |t| do_execute "ALTER TABLE #{t} NOCHECK CONSTRAINT ALL" }
         | 
| 142 | 
            +
                    tables.each { |t| do_execute "ALTER TABLE #{quote_table_name(t)} NOCHECK CONSTRAINT ALL" }
         | 
| 151 143 | 
             
                    yield
         | 
| 152 144 | 
             
                  ensure
         | 
| 153 | 
            -
                    tables.each { |t| do_execute "ALTER TABLE #{t} CHECK CONSTRAINT ALL" }
         | 
| 145 | 
            +
                    tables.each { |t| do_execute "ALTER TABLE #{quote_table_name(t)} CHECK CONSTRAINT ALL" }
         | 
| 154 146 | 
             
                  end
         | 
| 155 147 |  | 
| 156 148 | 
             
                  # === Abstract Adapter (Connection Management) ================== #
         | 
| @@ -230,6 +222,14 @@ module ActiveRecord | |
| 230 222 | 
             
                    @connection_options[:database_prefix]
         | 
| 231 223 | 
             
                  end
         | 
| 232 224 |  | 
| 225 | 
            +
                  def database_prefix_identifier(name)
         | 
| 226 | 
            +
                    if database_prefix_remote_server?
         | 
| 227 | 
            +
                      SQLServer::Utils.extract_identifiers("#{database_prefix}#{name}")
         | 
| 228 | 
            +
                    else
         | 
| 229 | 
            +
                      SQLServer::Utils.extract_identifiers(name)
         | 
| 230 | 
            +
                    end
         | 
| 231 | 
            +
                  end
         | 
| 232 | 
            +
             | 
| 233 233 | 
             
                  def version
         | 
| 234 234 | 
             
                    self.class::VERSION
         | 
| 235 235 | 
             
                  end
         | 
| @@ -327,6 +327,20 @@ module ActiveRecord | |
| 327 327 | 
             
                      NoDatabaseError.new(message)
         | 
| 328 328 | 
             
                    when /data would be truncated/
         | 
| 329 329 | 
             
                      ValueTooLong.new(message)
         | 
| 330 | 
            +
                    when /Column '(.*)' is not the same data type as referencing column '(.*)' in foreign key/
         | 
| 331 | 
            +
                      pk_id, fk_id = SQLServer::Utils.extract_identifiers($1), SQLServer::Utils.extract_identifiers($2)
         | 
| 332 | 
            +
                      MismatchedForeignKey.new(
         | 
| 333 | 
            +
                        self,
         | 
| 334 | 
            +
                        message: message,
         | 
| 335 | 
            +
                        table: fk_id.schema,
         | 
| 336 | 
            +
                        foreign_key: fk_id.object,
         | 
| 337 | 
            +
                        target_table: pk_id.schema,
         | 
| 338 | 
            +
                        primary_key: pk_id.object
         | 
| 339 | 
            +
                      )
         | 
| 340 | 
            +
                    when /Cannot insert the value NULL into column.*does not allow nulls/
         | 
| 341 | 
            +
                      NotNullViolation.new(message)
         | 
| 342 | 
            +
                    when /Arithmetic overflow error/
         | 
| 343 | 
            +
                      RangeError.new(message)
         | 
| 330 344 | 
             
                    else
         | 
| 331 345 | 
             
                      super
         | 
| 332 346 | 
             
                    end
         | 
| @@ -418,14 +432,11 @@ module ActiveRecord | |
| 418 432 | 
             
                  end
         | 
| 419 433 |  | 
| 420 434 | 
             
                  def version_year
         | 
| 421 | 
            -
                     | 
| 422 | 
            -
                     | 
| 423 | 
            -
             | 
| 424 | 
            -
             | 
| 425 | 
            -
             | 
| 426 | 
            -
                    rescue Exception => e
         | 
| 427 | 
            -
                      2016
         | 
| 428 | 
            -
                    end
         | 
| 435 | 
            +
                    vstring = _raw_select('SELECT @@version', fetch: :rows).first.first.to_s
         | 
| 436 | 
            +
                    return 2016 if vstring =~ /vNext/
         | 
| 437 | 
            +
                    /SQL Server (\d+)/.match(vstring).to_a.last.to_s.to_i
         | 
| 438 | 
            +
                  rescue Exception => e
         | 
| 439 | 
            +
                    2016
         | 
| 429 440 | 
             
                  end
         | 
| 430 441 |  | 
| 431 442 | 
             
                end
         | 
| @@ -48,7 +48,7 @@ module ActiveRecord | |
| 48 48 | 
             
                    create true
         | 
| 49 49 | 
             
                  end
         | 
| 50 50 |  | 
| 51 | 
            -
                  def structure_dump(filename)
         | 
| 51 | 
            +
                  def structure_dump(filename, extra_flags)
         | 
| 52 52 | 
             
                    command = [
         | 
| 53 53 | 
             
                      "defncopy",
         | 
| 54 54 | 
             
                      "-S #{Shellwords.escape(configuration['host'])}",
         | 
| @@ -71,7 +71,7 @@ module ActiveRecord | |
| 71 71 | 
             
                    File.open(filename, "w") { |file| file.puts dump }
         | 
| 72 72 | 
             
                  end
         | 
| 73 73 |  | 
| 74 | 
            -
                  def structure_load(filename)
         | 
| 74 | 
            +
                  def structure_load(filename, extra_flags)
         | 
| 75 75 | 
             
                    connection.execute File.read(filename)
         | 
| 76 76 | 
             
                  end
         | 
| 77 77 |  | 
| @@ -190,7 +190,8 @@ module Arel | |
| 190 190 |  | 
| 191 191 | 
             
                  def primary_Key_From_Table t
         | 
| 192 192 | 
             
                    return unless t
         | 
| 193 | 
            -
                    column_name = schema_cache.primary_keys(t.name) || | 
| 193 | 
            +
                    column_name = @connection.schema_cache.primary_keys(t.name) ||
         | 
| 194 | 
            +
                      @connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
         | 
| 194 195 | 
             
                    column_name ? t[column_name] : nil
         | 
| 195 196 | 
             
                  end
         | 
| 196 197 |  | 
| @@ -37,10 +37,6 @@ class AdapterTestSQLServer < ActiveRecord::TestCase | |
| 37 37 | 
             
                assert_equal 'SQLServer', connection.adapter_name
         | 
| 38 38 | 
             
              end
         | 
| 39 39 |  | 
| 40 | 
            -
              it 'supports migrations' do
         | 
| 41 | 
            -
                assert connection.supports_migrations?
         | 
| 42 | 
            -
              end
         | 
| 43 | 
            -
             | 
| 44 40 | 
             
              it 'support DDL in transactions' do
         | 
| 45 41 | 
             
                assert connection.supports_ddl_transactions?
         | 
| 46 42 | 
             
              end
         | 
| @@ -265,23 +261,23 @@ class AdapterTestSQLServer < ActiveRecord::TestCase | |
| 265 261 | 
             
                end
         | 
| 266 262 |  | 
| 267 263 | 
             
                it 'create integers when limit is 4' do
         | 
| 268 | 
            -
                  assert_equal 'integer', connection.type_to_sql(:integer, 4)
         | 
| 264 | 
            +
                  assert_equal 'integer', connection.type_to_sql(:integer, limit: 4)
         | 
| 269 265 | 
             
                end
         | 
| 270 266 |  | 
| 271 267 | 
             
                it 'create integers when limit is 3' do
         | 
| 272 | 
            -
                  assert_equal 'integer', connection.type_to_sql(:integer, 3)
         | 
| 268 | 
            +
                  assert_equal 'integer', connection.type_to_sql(:integer, limit: 3)
         | 
| 273 269 | 
             
                end
         | 
| 274 270 |  | 
| 275 271 | 
             
                it 'create smallints when limit is less than 3' do
         | 
| 276 | 
            -
                  assert_equal 'smallint', connection.type_to_sql(:integer, 2)
         | 
| 277 | 
            -
                  assert_equal 'smallint', connection.type_to_sql(:integer, 1)
         | 
| 272 | 
            +
                  assert_equal 'smallint', connection.type_to_sql(:integer, limit: 2)
         | 
| 273 | 
            +
                  assert_equal 'smallint', connection.type_to_sql(:integer, limit: 1)
         | 
| 278 274 | 
             
                end
         | 
| 279 275 |  | 
| 280 276 | 
             
                it 'create bigints when limit is greateer than 4' do
         | 
| 281 | 
            -
                  assert_equal 'bigint', connection.type_to_sql(:integer, 5)
         | 
| 282 | 
            -
                  assert_equal 'bigint', connection.type_to_sql(:integer, 6)
         | 
| 283 | 
            -
                  assert_equal 'bigint', connection.type_to_sql(:integer, 7)
         | 
| 284 | 
            -
                  assert_equal 'bigint', connection.type_to_sql(:integer, 8)
         | 
| 277 | 
            +
                  assert_equal 'bigint', connection.type_to_sql(:integer, limit: 5)
         | 
| 278 | 
            +
                  assert_equal 'bigint', connection.type_to_sql(:integer, limit: 6)
         | 
| 279 | 
            +
                  assert_equal 'bigint', connection.type_to_sql(:integer, limit: 7)
         | 
| 280 | 
            +
                  assert_equal 'bigint', connection.type_to_sql(:integer, limit: 8)
         | 
| 285 281 | 
             
                end
         | 
| 286 282 |  | 
| 287 283 | 
             
                it 'create floats when no limit supplied' do
         | 
    
        data/test/cases/coerced_tests.rb
    CHANGED
    
    | @@ -31,6 +31,9 @@ end | |
| 31 31 | 
             
            require 'models/event'
         | 
| 32 32 | 
             
            module ActiveRecord
         | 
| 33 33 | 
             
              class AdapterTest < ActiveRecord::TestCase
         | 
| 34 | 
            +
                # I really dont think we can support legacy binds.
         | 
| 35 | 
            +
                coerce_tests! :test_select_all_with_legacy_binds
         | 
| 36 | 
            +
             | 
| 34 37 | 
             
                # As far as I can tell, SQL Server does not support null bytes in strings.
         | 
| 35 38 | 
             
                coerce_tests! :test_update_prepared_statement
         | 
| 36 39 |  | 
| @@ -52,14 +55,14 @@ end | |
| 52 55 |  | 
| 53 56 | 
             
            require 'models/topic'
         | 
| 54 57 | 
             
            class AttributeMethodsTest < ActiveRecord::TestCase
         | 
| 55 | 
            -
              coerce_tests!  | 
| 58 | 
            +
              coerce_tests! %r{typecast attribute from select to false}
         | 
| 56 59 | 
             
              def test_typecast_attribute_from_select_to_false_coerced
         | 
| 57 60 | 
             
                Topic.create(:title => 'Budget')
         | 
| 58 61 | 
             
                topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
         | 
| 59 62 | 
             
                assert !topic.is_test?
         | 
| 60 63 | 
             
              end
         | 
| 61 64 |  | 
| 62 | 
            -
              coerce_tests!  | 
| 65 | 
            +
              coerce_tests! %r{typecast attribute from select to true}
         | 
| 63 66 | 
             
              def test_typecast_attribute_from_select_to_true_coerced
         | 
| 64 67 | 
             
                Topic.create(:title => 'Budget')
         | 
| 65 68 | 
             
                topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
         | 
| @@ -118,6 +121,15 @@ end | |
| 118 121 |  | 
| 119 122 |  | 
| 120 123 | 
             
            class CalculationsTest < ActiveRecord::TestCase
         | 
| 124 | 
            +
              # This fails randomly due to schema cache being lost?
         | 
| 125 | 
            +
              coerce_tests! :test_offset_is_kept
         | 
| 126 | 
            +
              def test_offset_is_kept_coerced
         | 
| 127 | 
            +
                Account.first
         | 
| 128 | 
            +
                queries = assert_sql { Account.offset(1).count }
         | 
| 129 | 
            +
                assert_equal 1, queries.length
         | 
| 130 | 
            +
                assert_match(/OFFSET/, queries.first)
         | 
| 131 | 
            +
              end
         | 
| 132 | 
            +
             | 
| 121 133 | 
             
              # Are decimal, not integer.
         | 
| 122 134 | 
             
              coerce_tests! :test_should_return_decimal_average_of_integer_field
         | 
| 123 135 | 
             
              def test_should_return_decimal_average_of_integer_field_coerced
         | 
| @@ -161,6 +173,29 @@ end | |
| 161 173 |  | 
| 162 174 |  | 
| 163 175 |  | 
| 176 | 
            +
            module ActiveRecord
         | 
| 177 | 
            +
              module ConnectionAdapters
         | 
| 178 | 
            +
                class QuoteARBaseTest < ActiveRecord::TestCase
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                  # Use our date format.
         | 
| 181 | 
            +
                  coerce_tests! :test_quote_ar_object
         | 
| 182 | 
            +
                  def test_quote_ar_object_coerced
         | 
| 183 | 
            +
                    value = DatetimePrimaryKey.new(id: @time)
         | 
| 184 | 
            +
                    assert_equal "'02-14-2017 12:34:56.79'",  @connection.quote(value)
         | 
| 185 | 
            +
                  end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                  # Use our date format.
         | 
| 188 | 
            +
                  coerce_tests! :test_type_cast_ar_object
         | 
| 189 | 
            +
                  def test_type_cast_ar_object_coerced
         | 
| 190 | 
            +
                    value = DatetimePrimaryKey.new(id: @time)
         | 
| 191 | 
            +
                    assert_equal "02-14-2017 12:34:56.79",  @connection.type_cast(value)
         | 
| 192 | 
            +
                  end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                end
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
            end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
             | 
| 164 199 |  | 
| 165 200 | 
             
            module ActiveRecord
         | 
| 166 201 | 
             
              class Migration
         | 
| @@ -289,6 +324,10 @@ end | |
| 289 324 |  | 
| 290 325 |  | 
| 291 326 | 
             
            module ActiveRecord
         | 
| 327 | 
            +
              class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
         | 
| 328 | 
            +
                # Skip this test with /tmp/my_schema_cache.yml path on Windows.
         | 
| 329 | 
            +
                coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
         | 
| 330 | 
            +
              end
         | 
| 292 331 | 
             
              class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
         | 
| 293 332 | 
             
                # We extend `local_database?` so that common VM IPs can be used.
         | 
| 294 333 | 
             
                coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
         | 
| @@ -375,12 +414,6 @@ class FinderTest < ActiveRecord::TestCase | |
| 375 414 | 
             
                end
         | 
| 376 415 | 
             
              end
         | 
| 377 416 |  | 
| 378 | 
            -
              coerce_tests! :test_string_sanitation
         | 
| 379 | 
            -
              def test_string_sanitation_coerced
         | 
| 380 | 
            -
                assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
         | 
| 381 | 
            -
                assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
         | 
| 382 | 
            -
              end
         | 
| 383 | 
            -
             | 
| 384 417 | 
             
              coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
         | 
| 385 418 | 
             
              def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
         | 
| 386 419 | 
             
                assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
         | 
| @@ -576,6 +609,15 @@ end | |
| 576 609 |  | 
| 577 610 |  | 
| 578 611 |  | 
| 612 | 
            +
            class PrimaryKeysTest < ActiveRecord::TestCase
         | 
| 613 | 
            +
              # Gonna trust Rails core for this. We end up with 2 querys vs 3 asserted
         | 
| 614 | 
            +
              # but as far as I can tell, this is only one for us anyway.
         | 
| 615 | 
            +
              coerce_tests! :test_create_without_primary_key_no_extra_query
         | 
| 616 | 
            +
            end
         | 
| 617 | 
            +
             | 
| 618 | 
            +
             | 
| 619 | 
            +
             | 
| 620 | 
            +
             | 
| 579 621 | 
             
            require 'models/task'
         | 
| 580 622 | 
             
            class QueryCacheTest < ActiveRecord::TestCase
         | 
| 581 623 | 
             
              coerce_tests! :test_cache_does_not_wrap_string_results_in_arrays
         | 
| @@ -619,6 +661,26 @@ class RelationTest < ActiveRecord::TestCase | |
| 619 661 | 
             
              # Leave it up to users to format selects/functions so HAVING works correctly.
         | 
| 620 662 | 
             
              coerce_tests! :test_multiple_where_and_having_clauses
         | 
| 621 663 | 
             
              coerce_tests! :test_having_with_binds_for_both_where_and_having
         | 
| 664 | 
            +
             | 
| 665 | 
            +
              # Find any limit via our expression.
         | 
| 666 | 
            +
              coerce_tests! %r{relations don't load all records in #inspect}
         | 
| 667 | 
            +
              def test_relations_dont_load_all_records_in_inspect_coerced
         | 
| 668 | 
            +
                assert_sql(/NEXT @0 ROWS.*@0 = \d+/) do
         | 
| 669 | 
            +
                  Post.all.inspect
         | 
| 670 | 
            +
                end
         | 
| 671 | 
            +
              end
         | 
| 672 | 
            +
             | 
| 673 | 
            +
              # I wanted to add `.order("author_id")` scope to avoid error: Column "posts.id" is invalid in the ORDER BY
         | 
| 674 | 
            +
              # However, this pull request on Rails core drops order on exists relation. https://github.com/rails/rails/pull/28699
         | 
| 675 | 
            +
              # so we are skipping all together.
         | 
| 676 | 
            +
              coerce_tests! :test_empty_complex_chained_relations
         | 
| 677 | 
            +
             | 
| 678 | 
            +
              # Use LEN() vs length() function.
         | 
| 679 | 
            +
              coerce_tests! :test_reverse_arel_assoc_order_with_function
         | 
| 680 | 
            +
              def test_reverse_arel_assoc_order_with_function_coerced
         | 
| 681 | 
            +
                topics = Topic.order(Arel.sql("LEN(title)") => :asc).reverse_order
         | 
| 682 | 
            +
                assert_equal topics(:second).title, topics.first.title
         | 
| 683 | 
            +
              end
         | 
| 622 684 | 
             
            end
         | 
| 623 685 |  | 
| 624 686 |  | 
| @@ -650,9 +712,6 @@ class SchemaDumperTest < ActiveRecord::TestCase | |
| 650 712 | 
             
                assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 38}, output
         | 
| 651 713 | 
             
              end
         | 
| 652 714 |  | 
| 653 | 
            -
              # This accidently returns the wrong number because of our tables too.
         | 
| 654 | 
            -
              coerce_tests! :test_types_line_up
         | 
| 655 | 
            -
             | 
| 656 715 | 
             
              # This is a poorly written test and really does not catch the bottom'ness it is meant too. Ours throw it off.
         | 
| 657 716 | 
             
              coerce_tests! :test_foreign_keys_are_dumped_at_the_bottom_to_circumvent_dependency_issues
         | 
| 658 717 |  | 
| @@ -816,3 +875,19 @@ module ActiveRecord | |
| 816 875 | 
             
                coerce_tests! :test_find_does_not_use_statement_cache_if_table_name_is_changed
         | 
| 817 876 | 
             
              end
         | 
| 818 877 | 
             
            end
         | 
| 878 | 
            +
             | 
| 879 | 
            +
             | 
| 880 | 
            +
             | 
| 881 | 
            +
             | 
| 882 | 
            +
            module ActiveRecord
         | 
| 883 | 
            +
              module ConnectionAdapters
         | 
| 884 | 
            +
                class SchemaCacheTest < ActiveRecord::TestCase
         | 
| 885 | 
            +
                  private
         | 
| 886 | 
            +
                  # We need to give the full path for this to work.
         | 
| 887 | 
            +
                  def schema_dump_path
         | 
| 888 | 
            +
                    File.join ARTest::SQLServer.root_activerecord, 'test/assets/schema_dump_5_1.yml'
         | 
| 889 | 
            +
                  end
         | 
| 890 | 
            +
                end
         | 
| 891 | 
            +
              end
         | 
| 892 | 
            +
            end
         | 
| 893 | 
            +
             | 
| @@ -36,7 +36,7 @@ class ColumnTestSQLServer < ActiveRecord::TestCase | |
| 36 36 | 
             
                it 'bigint(8)' do
         | 
| 37 37 | 
             
                  col = column('bigint')
         | 
| 38 38 | 
             
                  col.sql_type.must_equal           'bigint(8)'
         | 
| 39 | 
            -
                  col.type.must_equal               : | 
| 39 | 
            +
                  col.type.must_equal               :integer
         | 
| 40 40 | 
             
                  col.null.must_equal               true
         | 
| 41 41 | 
             
                  col.default.must_equal            42
         | 
| 42 42 | 
             
                  obj.bigint.must_equal             42
         | 
| @@ -23,9 +23,14 @@ module ActiveRecord | |
| 23 23 |  | 
| 24 24 | 
             
                let(:logger) { ActiveRecord::Base.logger }
         | 
| 25 25 |  | 
| 26 | 
            +
                setup :ensure_clean_rails_env
         | 
| 26 27 |  | 
| 27 28 | 
             
                private
         | 
| 28 29 |  | 
| 30 | 
            +
                def ensure_clean_rails_env
         | 
| 31 | 
            +
                  Rails.instance_variable_set(:@_env, nil) if defined?(::Rails)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 29 34 | 
             
                def host_windows?
         | 
| 30 35 | 
             
                  RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
         | 
| 31 36 | 
             
                end
         | 
| @@ -46,17 +46,6 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase | |
| 46 46 | 
             
                  end
         | 
| 47 47 | 
             
                end
         | 
| 48 48 |  | 
| 49 | 
            -
                it 'reload with lock when #lock! called' do
         | 
| 50 | 
            -
                  assert_nothing_raised do
         | 
| 51 | 
            -
                    Person.transaction do
         | 
| 52 | 
            -
                      person = Person.find 1
         | 
| 53 | 
            -
                      old, person.first_name = person.first_name, 'fooman'
         | 
| 54 | 
            -
                      person.lock!
         | 
| 55 | 
            -
                      assert_equal old, person.first_name
         | 
| 56 | 
            -
                    end
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
             | 
| 60 49 | 
             
                it 'can add a custom lock directive' do
         | 
| 61 50 | 
             
                  assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(HOLDLOCK, ROWLOCK\)| do
         | 
| 62 51 | 
             
                    Person.lock('WITH(HOLDLOCK, ROWLOCK)').load
         | 
| @@ -38,17 +38,17 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase | |
| 38 38 | 
             
                # Character Strings
         | 
| 39 39 | 
             
                assert_line :char_10,           type: 'char',         limit: 10,            precision: nil,   scale: nil,  default: "1234567890",           collation: nil
         | 
| 40 40 | 
             
                assert_line :varchar_50,        type: 'varchar',      limit: 50,            precision: nil,   scale: nil,  default: "test varchar_50",      collation: nil
         | 
| 41 | 
            -
                assert_line :varchar_max,       type: 'varchar_max',  limit:  | 
| 42 | 
            -
                assert_line :text,              type: 'text_basic',   limit:  | 
| 41 | 
            +
                assert_line :varchar_max,       type: 'varchar_max',  limit: nil,           precision: nil,   scale: nil,  default: "test varchar_max",     collation: nil
         | 
| 42 | 
            +
                assert_line :text,              type: 'text_basic',   limit: nil,           precision: nil,   scale: nil,  default: "test text",            collation: nil
         | 
| 43 43 | 
             
                # Unicode Character Strings
         | 
| 44 44 | 
             
                assert_line :nchar_10,          type: 'nchar',        limit: 10,            precision: nil,   scale: nil,  default: "12345678åå",           collation: nil
         | 
| 45 45 | 
             
                assert_line :nvarchar_50,       type: 'string',       limit: 50,            precision: nil,   scale: nil,  default: "test nvarchar_50 åå",  collation: nil
         | 
| 46 | 
            -
                assert_line :nvarchar_max,      type: 'text',         limit:  | 
| 47 | 
            -
                assert_line :ntext,             type: 'ntext',        limit:  | 
| 46 | 
            +
                assert_line :nvarchar_max,      type: 'text',         limit: nil,           precision: nil,   scale: nil,  default: "test nvarchar_max åå", collation: nil
         | 
| 47 | 
            +
                assert_line :ntext,             type: 'ntext',        limit: nil,           precision: nil,   scale: nil,  default: "test ntext åå",        collation: nil
         | 
| 48 48 | 
             
                # Binary Strings
         | 
| 49 49 | 
             
                assert_line :binary_49,         type: 'binary_basic', limit: 49,            precision: nil,   scale: nil,  default: nil
         | 
| 50 50 | 
             
                assert_line :varbinary_49,      type: 'varbinary',    limit: 49,            precision: nil,   scale: nil,  default: nil
         | 
| 51 | 
            -
                assert_line :varbinary_max,     type: 'binary',       limit:  | 
| 51 | 
            +
                assert_line :varbinary_max,     type: 'binary',       limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 52 52 | 
             
                # Other Data Types
         | 
| 53 53 | 
             
                assert_line :uniqueidentifier,  type: 'uuid',         limit: nil,           precision: nil,   scale: nil,  default: -> { "newid()" }
         | 
| 54 54 | 
             
                assert_line :timestamp,         type: 'ss_timestamp', limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| @@ -76,12 +76,12 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase | |
| 76 76 | 
             
                assert_line :decimal_col,     type: 'decimal',      limit: nil,          precision: 18,   scale: 0,   default: nil
         | 
| 77 77 | 
             
                assert_line :float_col,       type: 'float',        limit: nil,          precision: nil,  scale: nil, default: nil
         | 
| 78 78 | 
             
                assert_line :string_col,      type: 'string',       limit: nil,          precision: nil,  scale: nil, default: nil
         | 
| 79 | 
            -
                assert_line :text_col,        type: 'text',         limit:  | 
| 79 | 
            +
                assert_line :text_col,        type: 'text',         limit: nil,          precision: nil,  scale: nil, default: nil
         | 
| 80 80 | 
             
                assert_line :datetime_col,    type: 'datetime',     limit: nil,          precision: nil,  scale: nil, default: nil
         | 
| 81 81 | 
             
                assert_line :timestamp_col,   type: 'datetime',     limit: nil,          precision: nil,  scale: nil, default: nil
         | 
| 82 82 | 
             
                assert_line :time_col,        type: 'time',         limit: nil,          precision: 7,    scale: nil, default: nil
         | 
| 83 83 | 
             
                assert_line :date_col,        type: 'date',         limit: nil,          precision: nil,  scale: nil, default: nil
         | 
| 84 | 
            -
                assert_line :binary_col,      type: 'binary',       limit:  | 
| 84 | 
            +
                assert_line :binary_col,      type: 'binary',       limit: nil,          precision: nil,  scale: nil, default: nil
         | 
| 85 85 | 
             
                # Our type methods.
         | 
| 86 86 | 
             
                columns['real_col'].sql_type.must_equal         'real'
         | 
| 87 87 | 
             
                columns['money_col'].sql_type.must_equal        'money'
         | 
| @@ -107,14 +107,14 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase | |
| 107 107 | 
             
                assert_line :smallmoney_col,    type: 'smallmoney',     limit: nil,           precision: 10,    scale: 4,    default: nil
         | 
| 108 108 | 
             
                assert_line :char_col,          type: 'char',           limit: 1,             precision: nil,   scale: nil,  default: nil
         | 
| 109 109 | 
             
                assert_line :varchar_col,       type: 'varchar',        limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 110 | 
            -
                assert_line :text_basic_col,    type: 'text_basic',     limit:  | 
| 110 | 
            +
                assert_line :text_basic_col,    type: 'text_basic',     limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 111 111 | 
             
                assert_line :nchar_col,         type: 'nchar',          limit: 1,             precision: nil,   scale: nil,  default: nil
         | 
| 112 | 
            -
                assert_line :ntext_col,         type: 'ntext',          limit:  | 
| 112 | 
            +
                assert_line :ntext_col,         type: 'ntext',          limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 113 113 | 
             
                assert_line :binary_basic_col,  type: 'binary_basic',   limit: 1,             precision: nil,   scale: nil,  default: nil
         | 
| 114 114 | 
             
                assert_line :varbinary_col,     type: 'varbinary',      limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 115 115 | 
             
                assert_line :uuid_col,          type: 'uuid',           limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 116 116 | 
             
                assert_line :sstimestamp_col,   type: 'ss_timestamp',   limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 117 | 
            -
                assert_line :json_col,          type: 'text',           limit:  | 
| 117 | 
            +
                assert_line :json_col,          type: 'text',           limit: nil,           precision: nil,   scale: nil,  default: nil
         | 
| 118 118 | 
             
              end
         | 
| 119 119 |  | 
| 120 120 | 
             
              # Special Cases
         | 
| @@ -148,7 +148,7 @@ ActiveRecord::Schema.define do | |
| 148 148 |  | 
| 149 149 | 
             
              # Constraints
         | 
| 150 150 |  | 
| 151 | 
            -
              create_table(:sst_has_fks, force: true) { |t| t.column(:fk_id, : | 
| 151 | 
            +
              create_table(:sst_has_fks, force: true) { |t| t.column(:fk_id, :bigint, null: false) }
         | 
| 152 152 | 
             
              create_table(:sst_has_pks, force: true) { }
         | 
| 153 153 | 
             
              execute <<-ADDFKSQL
         | 
| 154 154 | 
             
                ALTER TABLE sst_has_fks
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: activerecord-sqlserver-adapter
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 5.0 | 
| 4 | 
            +
              version: 5.1.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ken Collins
         | 
| @@ -14,7 +14,7 @@ authors: | |
| 14 14 | 
             
            autorequire: 
         | 
| 15 15 | 
             
            bindir: bin
         | 
| 16 16 | 
             
            cert_chain: []
         | 
| 17 | 
            -
            date: 2017- | 
| 17 | 
            +
            date: 2017-05-29 00:00:00.000000000 Z
         | 
| 18 18 | 
             
            dependencies:
         | 
| 19 19 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 20 20 | 
             
              name: activerecord
         | 
| @@ -22,14 +22,14 @@ dependencies: | |
| 22 22 | 
             
                requirements:
         | 
| 23 23 | 
             
                - - "~>"
         | 
| 24 24 | 
             
                  - !ruby/object:Gem::Version
         | 
| 25 | 
            -
                    version: 5. | 
| 25 | 
            +
                    version: 5.1.0
         | 
| 26 26 | 
             
              type: :runtime
         | 
| 27 27 | 
             
              prerelease: false
         | 
| 28 28 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 29 29 | 
             
                requirements:
         | 
| 30 30 | 
             
                - - "~>"
         | 
| 31 31 | 
             
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            -
                    version: 5. | 
| 32 | 
            +
                    version: 5.1.0
         | 
| 33 33 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 34 34 | 
             
              name: tiny_tds
         | 
| 35 35 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -54,6 +54,7 @@ extra_rdoc_files: [] | |
| 54 54 | 
             
            files:
         | 
| 55 55 | 
             
            - ".gitignore"
         | 
| 56 56 | 
             
            - ".travis.yml"
         | 
| 57 | 
            +
            - BACKERS.md
         | 
| 57 58 | 
             
            - CHANGELOG.md
         | 
| 58 59 | 
             
            - CODE_OF_CONDUCT.md
         | 
| 59 60 | 
             
            - Gemfile
         | 
| @@ -288,3 +289,4 @@ test_files: | |
| 288 289 | 
             
            - test/support/rake_helpers.rb
         | 
| 289 290 | 
             
            - test/support/sql_counter_sqlserver.rb
         | 
| 290 291 | 
             
            - test/support/test_in_memory_oltp.rb
         | 
| 292 | 
            +
            has_rdoc: 
         |