activerecord-sqlserver-adapter 6.0.1 → 6.1.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/.github/workflows/ci.yml +26 -0
 - data/CHANGELOG.md +29 -46
 - data/README.md +32 -3
 - data/RUNNING_UNIT_TESTS.md +1 -1
 - data/VERSION +1 -1
 - data/activerecord-sqlserver-adapter.gemspec +1 -1
 - data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +2 -0
 - data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +5 -10
 - data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +9 -2
 - data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +2 -0
 - data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +2 -0
 - data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -4
 - data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +28 -16
 - data/lib/active_record/connection_adapters/sqlserver/quoting.rb +8 -7
 - data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -1
 - data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -3
 - data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +31 -9
 - data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +36 -7
 - data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +0 -1
 - data/lib/active_record/connection_adapters/sqlserver/transaction.rb +2 -2
 - data/lib/active_record/connection_adapters/sqlserver/type.rb +1 -0
 - data/lib/active_record/connection_adapters/sqlserver/type/date.rb +2 -1
 - data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
 - data/lib/active_record/connection_adapters/sqlserver/utils.rb +1 -1
 - data/lib/active_record/connection_adapters/sqlserver_adapter.rb +100 -69
 - data/lib/active_record/connection_adapters/sqlserver_column.rb +75 -19
 - data/lib/active_record/sqlserver_base.rb +9 -15
 - data/lib/active_record/tasks/sqlserver_database_tasks.rb +17 -14
 - data/lib/arel/visitors/sqlserver.rb +125 -40
 - data/test/cases/adapter_test_sqlserver.rb +50 -16
 - data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
 - data/test/cases/coerced_tests.rb +611 -78
 - data/test/cases/column_test_sqlserver.rb +9 -2
 - data/test/cases/disconnected_test_sqlserver.rb +39 -0
 - data/test/cases/execute_procedure_test_sqlserver.rb +9 -0
 - data/test/cases/fetch_test_sqlserver.rb +18 -0
 - data/test/cases/in_clause_test_sqlserver.rb +27 -0
 - data/test/cases/lateral_test_sqlserver.rb +35 -0
 - data/test/cases/migration_test_sqlserver.rb +51 -0
 - data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
 - data/test/cases/order_test_sqlserver.rb +7 -0
 - data/test/cases/primary_keys_test_sqlserver.rb +103 -0
 - data/test/cases/rake_test_sqlserver.rb +38 -2
 - data/test/cases/schema_dumper_test_sqlserver.rb +14 -3
 - data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
 - data/test/models/sqlserver/composite_pk.rb +9 -0
 - data/test/models/sqlserver/sst_string_collation.rb +3 -0
 - data/test/schema/sqlserver_specific_schema.rb +25 -0
 - data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
 - data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
 - data/test/support/sql_counter_sqlserver.rb +14 -12
 - metadata +29 -9
 - data/.travis.yml +0 -23
 - data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +0 -28
 
| 
         @@ -6,6 +6,7 @@ require "models/task" 
     | 
|
| 
       6 
6 
     | 
    
         
             
            require "models/post"
         
     | 
| 
       7 
7 
     | 
    
         
             
            require "models/subscriber"
         
     | 
| 
       8 
8 
     | 
    
         
             
            require "models/minimalistic"
         
     | 
| 
      
 9 
     | 
    
         
            +
            require "models/college"
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         
             
            class AdapterTestSQLServer < ActiveRecord::TestCase
         
     | 
| 
       11 
12 
     | 
    
         
             
              fixtures :tasks
         
     | 
| 
         @@ -42,17 +43,49 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       42 
43 
     | 
    
         
             
                assert connection.supports_ddl_transactions?
         
     | 
| 
       43 
44 
     | 
    
         
             
              end
         
     | 
| 
       44 
45 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
              it " 
     | 
| 
      
 46 
     | 
    
         
            +
              it "table exists works if table name prefixed by schema and owner" do
         
     | 
| 
       46 
47 
     | 
    
         
             
                begin
         
     | 
| 
       47 
48 
     | 
    
         
             
                  assert_equal "topics", Topic.table_name
         
     | 
| 
       48 
49 
     | 
    
         
             
                  assert Topic.table_exists?
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  # Test when owner included in table name.
         
     | 
| 
       49 
52 
     | 
    
         
             
                  Topic.table_name = "dbo.topics"
         
     | 
| 
       50 
     | 
    
         
            -
                  assert Topic.table_exists?, " 
     | 
| 
      
 53 
     | 
    
         
            +
                  assert Topic.table_exists?, "Topics table name of 'dbo.topics' should return true for exists."
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  # Test when database and owner included in table name.
         
     | 
| 
      
 56 
     | 
    
         
            +
                  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
         
     | 
| 
      
 57 
     | 
    
         
            +
                  Topic.table_name = "#{db_config.database}.dbo.topics"
         
     | 
| 
      
 58 
     | 
    
         
            +
                  assert Topic.table_exists?, "Topics table name of '[DATABASE].dbo.topics' should return true for exists."
         
     | 
| 
       51 
59 
     | 
    
         
             
                ensure
         
     | 
| 
       52 
60 
     | 
    
         
             
                  Topic.table_name = "topics"
         
     | 
| 
       53 
61 
     | 
    
         
             
                end
         
     | 
| 
       54 
62 
     | 
    
         
             
              end
         
     | 
| 
       55 
63 
     | 
    
         | 
| 
      
 64 
     | 
    
         
            +
              it "test table existence across database schemas" do
         
     | 
| 
      
 65 
     | 
    
         
            +
                arunit_connection = Topic.connection
         
     | 
| 
      
 66 
     | 
    
         
            +
                arunit2_connection = College.connection
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                arunit_database = arunit_connection.pool.db_config.database
         
     | 
| 
      
 69 
     | 
    
         
            +
                arunit2_database = arunit2_connection.pool.db_config.database
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                # Assert that connections use different default databases schemas.
         
     | 
| 
      
 72 
     | 
    
         
            +
                assert_not_equal arunit_database, arunit2_database
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                # Assert that the Topics table exists when using the Topics connection.
         
     | 
| 
      
 75 
     | 
    
         
            +
                assert arunit_connection.table_exists?('topics'), 'Topics table exists using table name'
         
     | 
| 
      
 76 
     | 
    
         
            +
                assert arunit_connection.table_exists?('dbo.topics'), 'Topics table exists using owner and table name'
         
     | 
| 
      
 77 
     | 
    
         
            +
                assert arunit_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using database, owner and table name'
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                # Assert that the Colleges table exists when using the Colleges connection.
         
     | 
| 
      
 80 
     | 
    
         
            +
                assert arunit2_connection.table_exists?('colleges'), 'College table exists using table name'
         
     | 
| 
      
 81 
     | 
    
         
            +
                assert arunit2_connection.table_exists?('dbo.colleges'), 'College table exists using owner and table name'
         
     | 
| 
      
 82 
     | 
    
         
            +
                assert arunit2_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'College table exists using database, owner and table name'
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                # Assert that the tables exist when using each others connection.
         
     | 
| 
      
 85 
     | 
    
         
            +
                assert arunit_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'Colleges table exists using Topics connection'
         
     | 
| 
      
 86 
     | 
    
         
            +
                assert arunit2_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using Colleges connection'
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
       56 
89 
     | 
    
         
             
              it "return true to insert sql query for inserts only" do
         
     | 
| 
       57 
90 
     | 
    
         
             
                assert connection.send(:insert_sql?, "INSERT...")
         
     | 
| 
       58 
91 
     | 
    
         
             
                assert connection.send(:insert_sql?, "EXEC sp_executesql N'INSERT INTO [fk_test_has_fks] ([fk_id]) VALUES (@0); SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident', N'@0 int', @0 = 0")
         
     | 
| 
         @@ -68,21 +101,23 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       68 
101 
     | 
    
         | 
| 
       69 
102 
     | 
    
         
             
              it "test bad connection" do
         
     | 
| 
       70 
103 
     | 
    
         
             
                assert_raise ActiveRecord::NoDatabaseError do
         
     | 
| 
       71 
     | 
    
         
            -
                   
     | 
| 
       72 
     | 
    
         
            -
                   
     | 
| 
      
 104 
     | 
    
         
            +
                  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
         
     | 
| 
      
 105 
     | 
    
         
            +
                  configuration = db_config.configuration_hash.merge(database: "inexistent_activerecord_unittest")
         
     | 
| 
      
 106 
     | 
    
         
            +
                  ActiveRecord::Base.sqlserver_connection configuration
         
     | 
| 
       73 
107 
     | 
    
         
             
                end
         
     | 
| 
       74 
108 
     | 
    
         
             
              end
         
     | 
| 
       75 
109 
     | 
    
         | 
| 
       76 
110 
     | 
    
         
             
              it "test database exists returns false if database does not exist" do
         
     | 
| 
       77 
     | 
    
         
            -
                 
     | 
| 
       78 
     | 
    
         
            -
                 
     | 
| 
      
 111 
     | 
    
         
            +
                db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
         
     | 
| 
      
 112 
     | 
    
         
            +
                configuration = db_config.configuration_hash.merge(database: "inexistent_activerecord_unittest")
         
     | 
| 
      
 113 
     | 
    
         
            +
                assert_not ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(configuration),
         
     | 
| 
       79 
114 
     | 
    
         
             
                           "expected database to not exist"
         
     | 
| 
       80 
115 
     | 
    
         
             
              end
         
     | 
| 
       81 
116 
     | 
    
         | 
| 
       82 
117 
     | 
    
         
             
              it "test database exists returns true when the database exists" do
         
     | 
| 
       83 
     | 
    
         
            -
                 
     | 
| 
       84 
     | 
    
         
            -
                assert ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?( 
     | 
| 
       85 
     | 
    
         
            -
                       "expected database #{ 
     | 
| 
      
 118 
     | 
    
         
            +
                db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
         
     | 
| 
      
 119 
     | 
    
         
            +
                assert ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(db_config.configuration_hash),
         
     | 
| 
      
 120 
     | 
    
         
            +
                       "expected database #{db_config.database} to exist"
         
     | 
| 
       86 
121 
     | 
    
         
             
              end
         
     | 
| 
       87 
122 
     | 
    
         | 
| 
       88 
123 
     | 
    
         
             
              describe "with different language" do
         
     | 
| 
         @@ -342,7 +377,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       342 
377 
     | 
    
         
             
                  assert !SSTestCustomersView.columns.blank?
         
     | 
| 
       343 
378 
     | 
    
         
             
                  assert_equal columns.size, SSTestCustomersView.columns.size
         
     | 
| 
       344 
379 
     | 
    
         
             
                  columns.each do |colname|
         
     | 
| 
       345 
     | 
    
         
            -
                    assert_instance_of ActiveRecord::ConnectionAdapters:: 
     | 
| 
      
 380 
     | 
    
         
            +
                    assert_instance_of ActiveRecord::ConnectionAdapters::SQLServer::Column,
         
     | 
| 
       346 
381 
     | 
    
         
             
                                       SSTestCustomersView.columns_hash[colname],
         
     | 
| 
       347 
382 
     | 
    
         
             
                                       "Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}"
         
     | 
| 
       348 
383 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -369,7 +404,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       369 
404 
     | 
    
         
             
                  assert !SSTestStringDefaultsView.columns.blank?
         
     | 
| 
       370 
405 
     | 
    
         
             
                  assert_equal columns.size, SSTestStringDefaultsView.columns.size
         
     | 
| 
       371 
406 
     | 
    
         
             
                  columns.each do |colname|
         
     | 
| 
       372 
     | 
    
         
            -
                    assert_instance_of ActiveRecord::ConnectionAdapters:: 
     | 
| 
      
 407 
     | 
    
         
            +
                    assert_instance_of ActiveRecord::ConnectionAdapters::SQLServer::Column,
         
     | 
| 
       373 
408 
     | 
    
         
             
                                       SSTestStringDefaultsView.columns_hash[colname],
         
     | 
| 
       374 
409 
     | 
    
         
             
                                       "Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}"
         
     | 
| 
       375 
410 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -434,12 +469,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       434 
469 
     | 
    
         
             
              describe "block writes to a database" do
         
     | 
| 
       435 
470 
     | 
    
         
             
                def setup
         
     | 
| 
       436 
471 
     | 
    
         
             
                  @conn = ActiveRecord::Base.connection
         
     | 
| 
       437 
     | 
    
         
            -
                  @connection_handler = ActiveRecord::Base.connection_handler
         
     | 
| 
       438 
472 
     | 
    
         
             
                end
         
     | 
| 
       439 
473 
     | 
    
         | 
| 
       440 
474 
     | 
    
         
             
                def test_errors_when_an_insert_query_is_called_while_preventing_writes
         
     | 
| 
       441 
475 
     | 
    
         
             
                  assert_raises(ActiveRecord::ReadOnlyError) do
         
     | 
| 
       442 
     | 
    
         
            -
                     
     | 
| 
      
 476 
     | 
    
         
            +
                    ActiveRecord::Base.while_preventing_writes do
         
     | 
| 
       443 
477 
     | 
    
         
             
                      @conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
         
     | 
| 
       444 
478 
     | 
    
         
             
                    end
         
     | 
| 
       445 
479 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -449,7 +483,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       449 
483 
     | 
    
         
             
                  @conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
         
     | 
| 
       450 
484 
     | 
    
         | 
| 
       451 
485 
     | 
    
         
             
                  assert_raises(ActiveRecord::ReadOnlyError) do
         
     | 
| 
       452 
     | 
    
         
            -
                     
     | 
| 
      
 486 
     | 
    
         
            +
                    ActiveRecord::Base.while_preventing_writes do
         
     | 
| 
       453 
487 
     | 
    
         
             
                      @conn.update("UPDATE [subscribers] SET [subscribers].[name] = 'Aidan' WHERE [subscribers].[nick] = 'aido'")
         
     | 
| 
       454 
488 
     | 
    
         
             
                    end
         
     | 
| 
       455 
489 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -459,7 +493,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       459 
493 
     | 
    
         
             
                  @conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
         
     | 
| 
       460 
494 
     | 
    
         | 
| 
       461 
495 
     | 
    
         
             
                  assert_raises(ActiveRecord::ReadOnlyError) do
         
     | 
| 
       462 
     | 
    
         
            -
                     
     | 
| 
      
 496 
     | 
    
         
            +
                    ActiveRecord::Base.while_preventing_writes do
         
     | 
| 
       463 
497 
     | 
    
         
             
                      @conn.execute("DELETE FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
         
     | 
| 
       464 
498 
     | 
    
         
             
                    end
         
     | 
| 
       465 
499 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -468,7 +502,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase 
     | 
|
| 
       468 
502 
     | 
    
         
             
                def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes
         
     | 
| 
       469 
503 
     | 
    
         
             
                  @conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
         
     | 
| 
       470 
504 
     | 
    
         | 
| 
       471 
     | 
    
         
            -
                   
     | 
| 
      
 505 
     | 
    
         
            +
                  ActiveRecord::Base.while_preventing_writes do
         
     | 
| 
       472 
506 
     | 
    
         
             
                    assert_equal 1, @conn.execute("SELECT * FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
         
     | 
| 
       473 
507 
     | 
    
         
             
                  end
         
     | 
| 
       474 
508 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "cases/helper_sqlserver"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "migrations/create_clients_and_change_column_collation"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class ChangeColumnCollationTestSqlServer < ActiveRecord::TestCase
         
     | 
| 
      
 7 
     | 
    
         
            +
              before do
         
     | 
| 
      
 8 
     | 
    
         
            +
                @old_verbose = ActiveRecord::Migration.verbose
         
     | 
| 
      
 9 
     | 
    
         
            +
                ActiveRecord::Migration.verbose = false
         
     | 
| 
      
 10 
     | 
    
         
            +
                CreateClientsAndChangeColumnCollation.new.up
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              after do
         
     | 
| 
      
 14 
     | 
    
         
            +
                CreateClientsAndChangeColumnCollation.new.down
         
     | 
| 
      
 15 
     | 
    
         
            +
                ActiveRecord::Migration.verbose = @old_verbose
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              def find_column(table, name)
         
     | 
| 
      
 19 
     | 
    
         
            +
                table.find { |column| column.name == name }
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              let(:clients_table) { connection.columns("clients") }
         
     | 
| 
      
 23 
     | 
    
         
            +
              let(:name_column) { find_column(clients_table, "name") }
         
     | 
| 
      
 24 
     | 
    
         
            +
              let(:code_column) { find_column(clients_table, "code") }
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              it "change column collation to other than default" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                _(name_column.collation).must_equal "SQL_Latin1_General_CP1_CS_AS"
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              it "change column collation to default" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                _(code_column.collation).must_equal "SQL_Latin1_General_CP1_CI_AS"
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
    
        data/test/cases/coerced_tests.rb
    CHANGED
    
    | 
         @@ -24,22 +24,35 @@ class UniquenessValidationTest < ActiveRecord::TestCase 
     | 
|
| 
       24 
24 
     | 
    
         
             
                end
         
     | 
| 
       25 
25 
     | 
    
         
             
              end
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
              #  
     | 
| 
       28 
     | 
    
         
            -
              coerce_tests! : 
     | 
| 
       29 
     | 
    
         
            -
              def  
     | 
| 
       30 
     | 
    
         
            -
                 
     | 
| 
       31 
     | 
    
         
            -
                skip if database_collation.include?("_CI_")
         
     | 
| 
      
 27 
     | 
    
         
            +
              # Same as original coerced test except that it handles default SQL Server case-insensitive collation.
         
     | 
| 
      
 28 
     | 
    
         
            +
              coerce_tests! :test_validate_uniqueness_by_default_database_collation
         
     | 
| 
      
 29 
     | 
    
         
            +
              def test_validate_uniqueness_by_default_database_collation_coerced
         
     | 
| 
      
 30 
     | 
    
         
            +
                Topic.validates_uniqueness_of(:author_email_address)
         
     | 
| 
       32 
31 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                 
     | 
| 
      
 32 
     | 
    
         
            +
                topic1 = Topic.new(author_email_address: "david@loudthinking.com")
         
     | 
| 
      
 33 
     | 
    
         
            +
                topic2 = Topic.new(author_email_address: "David@loudthinking.com")
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                assert_equal 1, Topic.where(author_email_address: "david@loudthinking.com").count
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                assert_not topic1.valid?
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_not topic1.save
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # Case insensitive collation (SQL_Latin1_General_CP1_CI_AS) by default.
         
     | 
| 
      
 41 
     | 
    
         
            +
                # Should not allow "David" if "david" exists.
         
     | 
| 
      
 42 
     | 
    
         
            +
                assert_not topic2.valid?
         
     | 
| 
      
 43 
     | 
    
         
            +
                assert_not topic2.save
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                assert_equal 1, Topic.where(author_email_address: "david@loudthinking.com").count
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert_equal 1, Topic.where(author_email_address: "David@loudthinking.com").count
         
     | 
| 
       34 
47 
     | 
    
         
             
              end
         
     | 
| 
       35 
48 
     | 
    
         
             
            end
         
     | 
| 
       36 
49 
     | 
    
         | 
| 
       37 
50 
     | 
    
         
             
            require "models/event"
         
     | 
| 
       38 
51 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       39 
52 
     | 
    
         
             
              class AdapterTest < ActiveRecord::TestCase
         
     | 
| 
       40 
     | 
    
         
            -
                #  
     | 
| 
       41 
     | 
    
         
            -
                coerce_tests! : 
     | 
| 
       42 
     | 
    
         
            -
                coerce_tests! : 
     | 
| 
      
 53 
     | 
    
         
            +
                # Legacy binds are not supported.
         
     | 
| 
      
 54 
     | 
    
         
            +
                coerce_tests! :test_select_all_insert_update_delete_with_casted_binds
         
     | 
| 
      
 55 
     | 
    
         
            +
                coerce_tests! :test_select_all_insert_update_delete_with_legacy_binds
         
     | 
| 
       43 
56 
     | 
    
         | 
| 
       44 
57 
     | 
    
         
             
                # As far as I can tell, SQL Server does not support null bytes in strings.
         
     | 
| 
       45 
58 
     | 
    
         
             
                coerce_tests! :test_update_prepared_statement
         
     | 
| 
         @@ -54,13 +67,63 @@ module ActiveRecord 
     | 
|
| 
       54 
67 
     | 
    
         
             
                    assert_not_nil error.cause
         
     | 
| 
       55 
68 
     | 
    
         
             
                  end
         
     | 
| 
       56 
69 
     | 
    
         
             
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 74 
     | 
    
         
            +
              class AdapterPreventWritesTest < ActiveRecord::TestCase
         
     | 
| 
      
 75 
     | 
    
         
            +
                # Fix randomly failing test. The loading of the model's schema was affecting the test.
         
     | 
| 
      
 76 
     | 
    
         
            +
                coerce_tests! :test_errors_when_an_insert_query_is_called_while_preventing_writes
         
     | 
| 
      
 77 
     | 
    
         
            +
                def test_errors_when_an_insert_query_is_called_while_preventing_writes_coerced
         
     | 
| 
      
 78 
     | 
    
         
            +
                  Subscriber.send(:load_schema!)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  original_test_errors_when_an_insert_query_is_called_while_preventing_writes
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
       57 
81 
     | 
    
         | 
| 
      
 82 
     | 
    
         
            +
                # Fix randomly failing test. The loading of the model's schema was affecting the test.
         
     | 
| 
      
 83 
     | 
    
         
            +
                coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
         
     | 
| 
      
 84 
     | 
    
         
            +
                def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes_coerced
         
     | 
| 
      
 85 
     | 
    
         
            +
                  Subscriber.send(:load_schema!)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                # Fix randomly failing test. The loading of the model's schema was affecting the test.
         
     | 
| 
      
 90 
     | 
    
         
            +
                coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
         
     | 
| 
      
 91 
     | 
    
         
            +
                def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes_coerced
         
     | 
| 
      
 92 
     | 
    
         
            +
                  Subscriber.send(:load_schema!)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
            end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 99 
     | 
    
         
            +
              class AdapterPreventWritesLegacyTest < ActiveRecord::TestCase
         
     | 
| 
       58 
100 
     | 
    
         
             
                # Fix randomly failing test. The loading of the model's schema was affecting the test.
         
     | 
| 
       59 
101 
     | 
    
         
             
                coerce_tests! :test_errors_when_an_insert_query_is_called_while_preventing_writes
         
     | 
| 
       60 
102 
     | 
    
         
             
                def test_errors_when_an_insert_query_is_called_while_preventing_writes_coerced
         
     | 
| 
       61 
103 
     | 
    
         
             
                  Subscriber.send(:load_schema!)
         
     | 
| 
       62 
104 
     | 
    
         
             
                  original_test_errors_when_an_insert_query_is_called_while_preventing_writes
         
     | 
| 
       63 
105 
     | 
    
         
             
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                # Fix randomly failing test. The loading of the model's schema was affecting the test.
         
     | 
| 
      
 108 
     | 
    
         
            +
                coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_slash_star_comment_is_called_while_preventing_writes
         
     | 
| 
      
 109 
     | 
    
         
            +
                def test_errors_when_an_insert_query_prefixed_by_a_slash_star_comment_is_called_while_preventing_writes_coerced
         
     | 
| 
      
 110 
     | 
    
         
            +
                  Subscriber.send(:load_schema!)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  original_test_errors_when_an_insert_query_prefixed_by_a_slash_star_comment_is_called_while_preventing_writes
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                # Fix randomly failing test. The loading of the model's schema was affecting the test.
         
     | 
| 
      
 115 
     | 
    
         
            +
                coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
         
     | 
| 
      
 116 
     | 
    
         
            +
                def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes_coerced
         
     | 
| 
      
 117 
     | 
    
         
            +
                  Subscriber.send(:load_schema!)
         
     | 
| 
      
 118 
     | 
    
         
            +
                  original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                # Fix randomly failing test. The loading of the model's schema was affecting the test.
         
     | 
| 
      
 122 
     | 
    
         
            +
                coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
         
     | 
| 
      
 123 
     | 
    
         
            +
                def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes_coerced
         
     | 
| 
      
 124 
     | 
    
         
            +
                  Subscriber.send(:load_schema!)
         
     | 
| 
      
 125 
     | 
    
         
            +
                  original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
       64 
127 
     | 
    
         
             
              end
         
     | 
| 
       65 
128 
     | 
    
         
             
            end
         
     | 
| 
       66 
129 
     | 
    
         | 
| 
         @@ -176,7 +239,7 @@ class BasicsTest < ActiveRecord::TestCase 
     | 
|
| 
       176 
239 
     | 
    
         
             
              # SQL Server does not have query for release_savepoint
         
     | 
| 
       177 
240 
     | 
    
         
             
              coerce_tests! %r{an empty transaction does not raise if preventing writes}
         
     | 
| 
       178 
241 
     | 
    
         
             
              test "an empty transaction does not raise if preventing writes coerced" do
         
     | 
| 
       179 
     | 
    
         
            -
                ActiveRecord::Base. 
     | 
| 
      
 242 
     | 
    
         
            +
                ActiveRecord::Base.while_preventing_writes do
         
     | 
| 
       180 
243 
     | 
    
         
             
                  assert_queries(1, ignore_none: true) do
         
     | 
| 
       181 
244 
     | 
    
         
             
                    Bird.transaction do
         
     | 
| 
       182 
245 
     | 
    
         
             
                      ActiveRecord::Base.connection.materialize_transactions
         
     | 
| 
         @@ -234,6 +297,55 @@ module ActiveRecord 
     | 
|
| 
       234 
297 
     | 
    
         
             
                coerce_tests! :test_statement_cache_with_find_by
         
     | 
| 
       235 
298 
     | 
    
         
             
                coerce_tests! :test_statement_cache_with_in_clause
         
     | 
| 
       236 
299 
     | 
    
         
             
                coerce_tests! :test_statement_cache_with_sql_string_literal
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
                # Same as original coerced test except prepared statements include `EXEC sp_executesql` wrapper.
         
     | 
| 
      
 302 
     | 
    
         
            +
                coerce_tests! :test_bind_params_to_sql_with_prepared_statements, :test_bind_params_to_sql_with_unprepared_statements
         
     | 
| 
      
 303 
     | 
    
         
            +
                def test_bind_params_to_sql_with_prepared_statements_coerced
         
     | 
| 
      
 304 
     | 
    
         
            +
                  assert_bind_params_to_sql_coerced(prepared: true)
         
     | 
| 
      
 305 
     | 
    
         
            +
                end
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
      
 307 
     | 
    
         
            +
                def test_bind_params_to_sql_with_unprepared_statements_coerced
         
     | 
| 
      
 308 
     | 
    
         
            +
                  @connection.unprepared_statement do
         
     | 
| 
      
 309 
     | 
    
         
            +
                    assert_bind_params_to_sql_coerced(prepared: false)
         
     | 
| 
      
 310 
     | 
    
         
            +
                  end
         
     | 
| 
      
 311 
     | 
    
         
            +
                end
         
     | 
| 
      
 312 
     | 
    
         
            +
             
     | 
| 
      
 313 
     | 
    
         
            +
                private
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                def assert_bind_params_to_sql_coerced(prepared:)
         
     | 
| 
      
 316 
     | 
    
         
            +
                  table = Author.quoted_table_name
         
     | 
| 
      
 317 
     | 
    
         
            +
                  pk = "#{table}.#{Author.quoted_primary_key}"
         
     | 
| 
      
 318 
     | 
    
         
            +
             
     | 
| 
      
 319 
     | 
    
         
            +
                  # prepared_statements: true
         
     | 
| 
      
 320 
     | 
    
         
            +
                  #
         
     | 
| 
      
 321 
     | 
    
         
            +
                  #   EXEC sp_executesql N'SELECT [authors].* FROM [authors] WHERE [authors].[id] IN (@0, @1, @2) OR [authors].[id] IS NULL)', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3
         
     | 
| 
      
 322 
     | 
    
         
            +
                  #
         
     | 
| 
      
 323 
     | 
    
         
            +
                  # prepared_statements: false
         
     | 
| 
      
 324 
     | 
    
         
            +
                  #
         
     | 
| 
      
 325 
     | 
    
         
            +
                  #   SELECT [authors].* FROM [authors] WHERE ([authors].[id] IN (1, 2, 3) OR [authors].[id] IS NULL)
         
     | 
| 
      
 326 
     | 
    
         
            +
                  #
         
     | 
| 
      
 327 
     | 
    
         
            +
                  sql_unprepared = "SELECT #{table}.* FROM #{table} WHERE (#{pk} IN (#{bind_params(1..3)}) OR #{pk} IS NULL)"
         
     | 
| 
      
 328 
     | 
    
         
            +
                  sql_prepared = "EXEC sp_executesql N'SELECT #{table}.* FROM #{table} WHERE (#{pk} IN (#{bind_params(1..3)}) OR #{pk} IS NULL)', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3"
         
     | 
| 
      
 329 
     | 
    
         
            +
             
     | 
| 
      
 330 
     | 
    
         
            +
                  authors = Author.where(id: [1, 2, 3, nil])
         
     | 
| 
      
 331 
     | 
    
         
            +
                  assert_equal sql_unprepared, @connection.to_sql(authors.arel)
         
     | 
| 
      
 332 
     | 
    
         
            +
                  assert_sql(prepared ? sql_prepared : sql_unprepared) { assert_equal 3, authors.length }
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                  # prepared_statements: true
         
     | 
| 
      
 335 
     | 
    
         
            +
                  #
         
     | 
| 
      
 336 
     | 
    
         
            +
                  #   EXEC sp_executesql N'SELECT [authors].* FROM [authors] WHERE [authors].[id] IN (@0, @1, @2)', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3
         
     | 
| 
      
 337 
     | 
    
         
            +
                  #
         
     | 
| 
      
 338 
     | 
    
         
            +
                  # prepared_statements: false
         
     | 
| 
      
 339 
     | 
    
         
            +
                  #
         
     | 
| 
      
 340 
     | 
    
         
            +
                  #   SELECT [authors].* FROM [authors] WHERE [authors].[id] IN (1, 2, 3)
         
     | 
| 
      
 341 
     | 
    
         
            +
                  #
         
     | 
| 
      
 342 
     | 
    
         
            +
                  sql_unprepared = "SELECT #{table}.* FROM #{table} WHERE #{pk} IN (#{bind_params(1..3)})"
         
     | 
| 
      
 343 
     | 
    
         
            +
                  sql_prepared = "EXEC sp_executesql N'SELECT #{table}.* FROM #{table} WHERE #{pk} IN (#{bind_params(1..3)})', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3"
         
     | 
| 
      
 344 
     | 
    
         
            +
             
     | 
| 
      
 345 
     | 
    
         
            +
                  authors = Author.where(id: [1, 2, 3, 9223372036854775808])
         
     | 
| 
      
 346 
     | 
    
         
            +
                  assert_equal sql_unprepared, @connection.to_sql(authors.arel)
         
     | 
| 
      
 347 
     | 
    
         
            +
                  assert_sql(prepared ? sql_prepared : sql_unprepared) { assert_equal 3, authors.length }
         
     | 
| 
      
 348 
     | 
    
         
            +
                end
         
     | 
| 
       237 
349 
     | 
    
         
             
              end
         
     | 
| 
       238 
350 
     | 
    
         
             
            end
         
     | 
| 
       239 
351 
     | 
    
         | 
| 
         @@ -256,11 +368,112 @@ class CalculationsTest < ActiveRecord::TestCase 
     | 
|
| 
       256 
368 
     | 
    
         
             
                original_test_offset_is_kept
         
     | 
| 
       257 
369 
     | 
    
         
             
              end
         
     | 
| 
       258 
370 
     | 
    
         | 
| 
       259 
     | 
    
         
            -
              #  
     | 
| 
      
 371 
     | 
    
         
            +
              # The SQL Server `AVG()` function for a list of integers returns an integer (not a decimal).
         
     | 
| 
       260 
372 
     | 
    
         
             
              coerce_tests! :test_should_return_decimal_average_of_integer_field
         
     | 
| 
       261 
373 
     | 
    
         
             
              def test_should_return_decimal_average_of_integer_field_coerced
         
     | 
| 
       262 
374 
     | 
    
         
             
                value = Account.average(:id)
         
     | 
| 
       263 
     | 
    
         
            -
                assert_equal  
     | 
| 
      
 375 
     | 
    
         
            +
                assert_equal 3, value
         
     | 
| 
      
 376 
     | 
    
         
            +
              end
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
              # In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
         
     | 
| 
      
 379 
     | 
    
         
            +
              # Match SQL Server limit implementation.
         
     | 
| 
      
 380 
     | 
    
         
            +
              coerce_tests! :test_select_avg_with_group_by_as_virtual_attribute_with_sql
         
     | 
| 
      
 381 
     | 
    
         
            +
              def test_select_avg_with_group_by_as_virtual_attribute_with_sql_coerced
         
     | 
| 
      
 382 
     | 
    
         
            +
                rails_core = companies(:rails_core)
         
     | 
| 
      
 383 
     | 
    
         
            +
             
     | 
| 
      
 384 
     | 
    
         
            +
                sql = <<~SQL
         
     | 
| 
      
 385 
     | 
    
         
            +
                  SELECT firm_id, AVG(CAST(credit_limit AS DECIMAL)) AS avg_credit_limit
         
     | 
| 
      
 386 
     | 
    
         
            +
                  FROM accounts
         
     | 
| 
      
 387 
     | 
    
         
            +
                  WHERE firm_id = ?
         
     | 
| 
      
 388 
     | 
    
         
            +
                  GROUP BY firm_id
         
     | 
| 
      
 389 
     | 
    
         
            +
                  ORDER BY firm_id
         
     | 
| 
      
 390 
     | 
    
         
            +
                  OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
         
     | 
| 
      
 391 
     | 
    
         
            +
                SQL
         
     | 
| 
      
 392 
     | 
    
         
            +
             
     | 
| 
      
 393 
     | 
    
         
            +
                account = Account.find_by_sql([sql, rails_core]).first
         
     | 
| 
      
 394 
     | 
    
         
            +
             
     | 
| 
      
 395 
     | 
    
         
            +
                # id was not selected, so it should be nil
         
     | 
| 
      
 396 
     | 
    
         
            +
                # (cannot select id because it wasn't used in the GROUP BY clause)
         
     | 
| 
      
 397 
     | 
    
         
            +
                assert_nil account.id
         
     | 
| 
      
 398 
     | 
    
         
            +
             
     | 
| 
      
 399 
     | 
    
         
            +
                # firm_id was explicitly selected, so it should be present
         
     | 
| 
      
 400 
     | 
    
         
            +
                assert_equal(rails_core, account.firm)
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
                # avg_credit_limit should be present as a virtual attribute
         
     | 
| 
      
 403 
     | 
    
         
            +
                assert_equal(52.5, account.avg_credit_limit)
         
     | 
| 
      
 404 
     | 
    
         
            +
              end
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
      
 406 
     | 
    
         
            +
              # In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
         
     | 
| 
      
 407 
     | 
    
         
            +
              # Order column must be in the GROUP clause.
         
     | 
| 
      
 408 
     | 
    
         
            +
              coerce_tests! :test_select_avg_with_group_by_as_virtual_attribute_with_ar
         
     | 
| 
      
 409 
     | 
    
         
            +
              def test_select_avg_with_group_by_as_virtual_attribute_with_ar_coerced
         
     | 
| 
      
 410 
     | 
    
         
            +
                rails_core = companies(:rails_core)
         
     | 
| 
      
 411 
     | 
    
         
            +
             
     | 
| 
      
 412 
     | 
    
         
            +
                account = Account
         
     | 
| 
      
 413 
     | 
    
         
            +
                            .select(:firm_id, "AVG(CAST(credit_limit AS DECIMAL)) AS avg_credit_limit")
         
     | 
| 
      
 414 
     | 
    
         
            +
                            .where(firm: rails_core)
         
     | 
| 
      
 415 
     | 
    
         
            +
                            .group(:firm_id)
         
     | 
| 
      
 416 
     | 
    
         
            +
                            .order(:firm_id)
         
     | 
| 
      
 417 
     | 
    
         
            +
                            .take!
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
      
 419 
     | 
    
         
            +
                # id was not selected, so it should be nil
         
     | 
| 
      
 420 
     | 
    
         
            +
                # (cannot select id because it wasn't used in the GROUP BY clause)
         
     | 
| 
      
 421 
     | 
    
         
            +
                assert_nil account.id
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
                # firm_id was explicitly selected, so it should be present
         
     | 
| 
      
 424 
     | 
    
         
            +
                assert_equal(rails_core, account.firm)
         
     | 
| 
      
 425 
     | 
    
         
            +
             
     | 
| 
      
 426 
     | 
    
         
            +
                # avg_credit_limit should be present as a virtual attribute
         
     | 
| 
      
 427 
     | 
    
         
            +
                assert_equal(52.5, account.avg_credit_limit)
         
     | 
| 
      
 428 
     | 
    
         
            +
              end
         
     | 
| 
      
 429 
     | 
    
         
            +
             
     | 
| 
      
 430 
     | 
    
         
            +
              # In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
         
     | 
| 
      
 431 
     | 
    
         
            +
              # SELECT columns must be in the GROUP clause.
         
     | 
| 
      
 432 
     | 
    
         
            +
              # Match SQL Server limit implementation.
         
     | 
| 
      
 433 
     | 
    
         
            +
              coerce_tests! :test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql
         
     | 
| 
      
 434 
     | 
    
         
            +
              def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql_coerced
         
     | 
| 
      
 435 
     | 
    
         
            +
                rails_core = companies(:rails_core)
         
     | 
| 
      
 436 
     | 
    
         
            +
             
     | 
| 
      
 437 
     | 
    
         
            +
                sql = <<~SQL
         
     | 
| 
      
 438 
     | 
    
         
            +
                  SELECT companies.*, AVG(CAST(accounts.credit_limit AS DECIMAL)) AS avg_credit_limit
         
     | 
| 
      
 439 
     | 
    
         
            +
                  FROM companies
         
     | 
| 
      
 440 
     | 
    
         
            +
                  INNER JOIN accounts ON companies.id = accounts.firm_id
         
     | 
| 
      
 441 
     | 
    
         
            +
                  WHERE companies.id = ?
         
     | 
| 
      
 442 
     | 
    
         
            +
                  GROUP BY companies.id, companies.type, companies.firm_id, companies.firm_name, companies.name, companies.client_of, companies.rating, companies.account_id, companies.description
         
     | 
| 
      
 443 
     | 
    
         
            +
                  ORDER BY companies.id
         
     | 
| 
      
 444 
     | 
    
         
            +
                  OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
         
     | 
| 
      
 445 
     | 
    
         
            +
                SQL
         
     | 
| 
      
 446 
     | 
    
         
            +
             
     | 
| 
      
 447 
     | 
    
         
            +
                firm = DependentFirm.find_by_sql([sql, rails_core]).first
         
     | 
| 
      
 448 
     | 
    
         
            +
             
     | 
| 
      
 449 
     | 
    
         
            +
                # all the DependentFirm attributes should be present
         
     | 
| 
      
 450 
     | 
    
         
            +
                assert_equal rails_core, firm
         
     | 
| 
      
 451 
     | 
    
         
            +
                assert_equal rails_core.name, firm.name
         
     | 
| 
      
 452 
     | 
    
         
            +
             
     | 
| 
      
 453 
     | 
    
         
            +
                # avg_credit_limit should be present as a virtual attribute
         
     | 
| 
      
 454 
     | 
    
         
            +
                assert_equal(52.5, firm.avg_credit_limit)
         
     | 
| 
      
 455 
     | 
    
         
            +
              end
         
     | 
| 
      
 456 
     | 
    
         
            +
             
     | 
| 
      
 457 
     | 
    
         
            +
             
     | 
| 
      
 458 
     | 
    
         
            +
              # In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
         
     | 
| 
      
 459 
     | 
    
         
            +
              # SELECT columns must be in the GROUP clause.
         
     | 
| 
      
 460 
     | 
    
         
            +
              coerce_tests! :test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar
         
     | 
| 
      
 461 
     | 
    
         
            +
              def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar_coerced
         
     | 
| 
      
 462 
     | 
    
         
            +
                rails_core = companies(:rails_core)
         
     | 
| 
      
 463 
     | 
    
         
            +
             
     | 
| 
      
 464 
     | 
    
         
            +
                firm = DependentFirm
         
     | 
| 
      
 465 
     | 
    
         
            +
                         .select("companies.*", "AVG(CAST(accounts.credit_limit AS DECIMAL)) AS avg_credit_limit")
         
     | 
| 
      
 466 
     | 
    
         
            +
                         .where(id: rails_core)
         
     | 
| 
      
 467 
     | 
    
         
            +
                         .joins(:account)
         
     | 
| 
      
 468 
     | 
    
         
            +
                         .group(:id, :type, :firm_id, :firm_name, :name, :client_of, :rating, :account_id, :description)
         
     | 
| 
      
 469 
     | 
    
         
            +
                         .take!
         
     | 
| 
      
 470 
     | 
    
         
            +
             
     | 
| 
      
 471 
     | 
    
         
            +
                # all the DependentFirm attributes should be present
         
     | 
| 
      
 472 
     | 
    
         
            +
                assert_equal rails_core, firm
         
     | 
| 
      
 473 
     | 
    
         
            +
                assert_equal rails_core.name, firm.name
         
     | 
| 
      
 474 
     | 
    
         
            +
             
     | 
| 
      
 475 
     | 
    
         
            +
                # avg_credit_limit should be present as a virtual attribute
         
     | 
| 
      
 476 
     | 
    
         
            +
                assert_equal(52.5, firm.avg_credit_limit)
         
     | 
| 
       264 
477 
     | 
    
         
             
              end
         
     | 
| 
       265 
478 
     | 
    
         | 
| 
       266 
479 
     | 
    
         
             
              # Match SQL Server limit implementation
         
     | 
| 
         @@ -329,14 +542,18 @@ module ActiveRecord 
     | 
|
| 
       329 
542 
     | 
    
         
             
                  coerce_tests! :test_quote_ar_object
         
     | 
| 
       330 
543 
     | 
    
         
             
                  def test_quote_ar_object_coerced
         
     | 
| 
       331 
544 
     | 
    
         
             
                    value = DatetimePrimaryKey.new(id: @time)
         
     | 
| 
       332 
     | 
    
         
            -
                     
     | 
| 
      
 545 
     | 
    
         
            +
                    assert_deprecated do
         
     | 
| 
      
 546 
     | 
    
         
            +
                      assert_equal "'02-14-2017 12:34:56.79'", @connection.quote(value)
         
     | 
| 
      
 547 
     | 
    
         
            +
                    end
         
     | 
| 
       333 
548 
     | 
    
         
             
                  end
         
     | 
| 
       334 
549 
     | 
    
         | 
| 
       335 
550 
     | 
    
         
             
                  # Use our date format.
         
     | 
| 
       336 
551 
     | 
    
         
             
                  coerce_tests! :test_type_cast_ar_object
         
     | 
| 
       337 
552 
     | 
    
         
             
                  def test_type_cast_ar_object_coerced
         
     | 
| 
       338 
553 
     | 
    
         
             
                    value = DatetimePrimaryKey.new(id: @time)
         
     | 
| 
       339 
     | 
    
         
            -
                     
     | 
| 
      
 554 
     | 
    
         
            +
                    assert_deprecated do
         
     | 
| 
      
 555 
     | 
    
         
            +
                      assert_equal "02-14-2017 12:34:56.79", @connection.type_cast(value)
         
     | 
| 
      
 556 
     | 
    
         
            +
                    end
         
     | 
| 
       340 
557 
     | 
    
         
             
                  end
         
     | 
| 
       341 
558 
     | 
    
         
             
                end
         
     | 
| 
       342 
559 
     | 
    
         
             
              end
         
     | 
| 
         @@ -396,39 +613,6 @@ module ActiveRecord 
     | 
|
| 
       396 
613 
     | 
    
         
             
            end
         
     | 
| 
       397 
614 
     | 
    
         | 
| 
       398 
615 
     | 
    
         
             
            class MigrationTest < ActiveRecord::TestCase
         
     | 
| 
       399 
     | 
    
         
            -
              # We do not have do the DecimalWithoutScale type.
         
     | 
| 
       400 
     | 
    
         
            -
              coerce_tests! :test_add_table_with_decimals
         
     | 
| 
       401 
     | 
    
         
            -
              def test_add_table_with_decimals_coerced
         
     | 
| 
       402 
     | 
    
         
            -
                Person.connection.drop_table :big_numbers rescue nil
         
     | 
| 
       403 
     | 
    
         
            -
                assert !BigNumber.table_exists?
         
     | 
| 
       404 
     | 
    
         
            -
                GiveMeBigNumbers.up
         
     | 
| 
       405 
     | 
    
         
            -
                BigNumber.reset_column_information
         
     | 
| 
       406 
     | 
    
         
            -
                assert BigNumber.create(
         
     | 
| 
       407 
     | 
    
         
            -
                  :bank_balance => 1586.43,
         
     | 
| 
       408 
     | 
    
         
            -
                  :big_bank_balance => BigDecimal("1000234000567.95"),
         
     | 
| 
       409 
     | 
    
         
            -
                  :world_population => 6000000000,
         
     | 
| 
       410 
     | 
    
         
            -
                  :my_house_population => 3,
         
     | 
| 
       411 
     | 
    
         
            -
                  :value_of_e => BigDecimal("2.7182818284590452353602875")
         
     | 
| 
       412 
     | 
    
         
            -
                )
         
     | 
| 
       413 
     | 
    
         
            -
                b = BigNumber.first
         
     | 
| 
       414 
     | 
    
         
            -
                assert_not_nil b
         
     | 
| 
       415 
     | 
    
         
            -
                assert_not_nil b.bank_balance
         
     | 
| 
       416 
     | 
    
         
            -
                assert_not_nil b.big_bank_balance
         
     | 
| 
       417 
     | 
    
         
            -
                assert_not_nil b.world_population
         
     | 
| 
       418 
     | 
    
         
            -
                assert_not_nil b.my_house_population
         
     | 
| 
       419 
     | 
    
         
            -
                assert_not_nil b.value_of_e
         
     | 
| 
       420 
     | 
    
         
            -
                assert_kind_of BigDecimal, b.world_population
         
     | 
| 
       421 
     | 
    
         
            -
                assert_equal "6000000000.0", b.world_population.to_s
         
     | 
| 
       422 
     | 
    
         
            -
                assert_kind_of Integer, b.my_house_population
         
     | 
| 
       423 
     | 
    
         
            -
                assert_equal 3, b.my_house_population
         
     | 
| 
       424 
     | 
    
         
            -
                assert_kind_of BigDecimal, b.bank_balance
         
     | 
| 
       425 
     | 
    
         
            -
                assert_equal BigDecimal("1586.43"), b.bank_balance
         
     | 
| 
       426 
     | 
    
         
            -
                assert_kind_of BigDecimal, b.big_bank_balance
         
     | 
| 
       427 
     | 
    
         
            -
                assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
         
     | 
| 
       428 
     | 
    
         
            -
                GiveMeBigNumbers.down
         
     | 
| 
       429 
     | 
    
         
            -
                assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
         
     | 
| 
       430 
     | 
    
         
            -
              end
         
     | 
| 
       431 
     | 
    
         
            -
             
     | 
| 
       432 
616 
     | 
    
         
             
              # For some reason our tests set Rails.@_env which breaks test env switching.
         
     | 
| 
       433 
617 
     | 
    
         
             
              coerce_tests! :test_internal_metadata_stores_environment_when_other_data_exists
         
     | 
| 
       434 
618 
     | 
    
         
             
              coerce_tests! :test_internal_metadata_stores_environment
         
     | 
| 
         @@ -584,11 +768,6 @@ module ActiveRecord 
     | 
|
| 
       584 
768 
     | 
    
         
             
                end
         
     | 
| 
       585 
769 
     | 
    
         
             
              end
         
     | 
| 
       586 
770 
     | 
    
         | 
| 
       587 
     | 
    
         
            -
              class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
         
     | 
| 
       588 
     | 
    
         
            -
                # Skip this test with /tmp/my_schema_cache.yml path on Windows.
         
     | 
| 
       589 
     | 
    
         
            -
                coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
         
     | 
| 
       590 
     | 
    
         
            -
              end
         
     | 
| 
       591 
     | 
    
         
            -
             
     | 
| 
       592 
771 
     | 
    
         
             
              class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
         
     | 
| 
       593 
772 
     | 
    
         
             
                # We extend `local_database?` so that common VM IPs can be used.
         
     | 
| 
       594 
773 
     | 
    
         
             
                coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
         
     | 
| 
         @@ -653,7 +832,11 @@ class EagerAssociationTest < ActiveRecord::TestCase 
     | 
|
| 
       653 
832 
     | 
    
         
             
            end
         
     | 
| 
       654 
833 
     | 
    
         | 
| 
       655 
834 
     | 
    
         
             
            require "models/topic"
         
     | 
| 
      
 835 
     | 
    
         
            +
            require "models/customer"
         
     | 
| 
      
 836 
     | 
    
         
            +
            require "models/non_primary_key"
         
     | 
| 
       656 
837 
     | 
    
         
             
            class FinderTest < ActiveRecord::TestCase
         
     | 
| 
      
 838 
     | 
    
         
            +
              fixtures :customers, :topics, :authors
         
     | 
| 
      
 839 
     | 
    
         
            +
             
     | 
| 
       657 
840 
     | 
    
         
             
              # We have implicit ordering, via FETCH.
         
     | 
| 
       658 
841 
     | 
    
         
             
              coerce_tests! %r{doesn't have implicit ordering},
         
     | 
| 
       659 
842 
     | 
    
         
             
                            :test_find_doesnt_have_implicit_ordering
         
     | 
| 
         @@ -698,6 +881,87 @@ class FinderTest < ActiveRecord::TestCase 
     | 
|
| 
       698 
881 
     | 
    
         
             
                  end
         
     | 
| 
       699 
882 
     | 
    
         
             
                end
         
     | 
| 
       700 
883 
     | 
    
         
             
              end
         
     | 
| 
      
 884 
     | 
    
         
            +
             
     | 
| 
      
 885 
     | 
    
         
            +
              # Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
         
     | 
| 
      
 886 
     | 
    
         
            +
              coerce_tests! :test_include_on_unloaded_relation_with_match
         
     | 
| 
      
 887 
     | 
    
         
            +
              def test_include_on_unloaded_relation_with_match_coerced
         
     | 
| 
      
 888 
     | 
    
         
            +
                assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
         
     | 
| 
      
 889 
     | 
    
         
            +
                  assert_equal true, Customer.where(name: "David").include?(customers(:david))
         
     | 
| 
      
 890 
     | 
    
         
            +
                end
         
     | 
| 
      
 891 
     | 
    
         
            +
              end
         
     | 
| 
      
 892 
     | 
    
         
            +
             
     | 
| 
      
 893 
     | 
    
         
            +
              # Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
         
     | 
| 
      
 894 
     | 
    
         
            +
              coerce_tests! :test_include_on_unloaded_relation_without_match
         
     | 
| 
      
 895 
     | 
    
         
            +
              def test_include_on_unloaded_relation_without_match_coerced
         
     | 
| 
      
 896 
     | 
    
         
            +
                assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
         
     | 
| 
      
 897 
     | 
    
         
            +
                  assert_equal false, Customer.where(name: "David").include?(customers(:mary))
         
     | 
| 
      
 898 
     | 
    
         
            +
                end
         
     | 
| 
      
 899 
     | 
    
         
            +
              end
         
     | 
| 
      
 900 
     | 
    
         
            +
             
     | 
| 
      
 901 
     | 
    
         
            +
              # Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
         
     | 
| 
      
 902 
     | 
    
         
            +
              coerce_tests! :test_member_on_unloaded_relation_with_match
         
     | 
| 
      
 903 
     | 
    
         
            +
              def test_member_on_unloaded_relation_with_match_coerced
         
     | 
| 
      
 904 
     | 
    
         
            +
                assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
         
     | 
| 
      
 905 
     | 
    
         
            +
                  assert_equal true, Customer.where(name: "David").member?(customers(:david))
         
     | 
| 
      
 906 
     | 
    
         
            +
                end
         
     | 
| 
      
 907 
     | 
    
         
            +
              end
         
     | 
| 
      
 908 
     | 
    
         
            +
             
     | 
| 
      
 909 
     | 
    
         
            +
              # Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
         
     | 
| 
      
 910 
     | 
    
         
            +
              coerce_tests! :test_member_on_unloaded_relation_without_match
         
     | 
| 
      
 911 
     | 
    
         
            +
              def test_member_on_unloaded_relation_without_match_coerced
         
     | 
| 
      
 912 
     | 
    
         
            +
                assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
         
     | 
| 
      
 913 
     | 
    
         
            +
                  assert_equal false, Customer.where(name: "David").member?(customers(:mary))
         
     | 
| 
      
 914 
     | 
    
         
            +
                end
         
     | 
| 
      
 915 
     | 
    
         
            +
              end
         
     | 
| 
      
 916 
     | 
    
         
            +
             
     | 
| 
      
 917 
     | 
    
         
            +
              # Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
         
     | 
| 
      
 918 
     | 
    
         
            +
              coerce_tests! :test_implicit_order_column_is_configurable
         
     | 
| 
      
 919 
     | 
    
         
            +
              def test_implicit_order_column_is_configurable_coerced
         
     | 
| 
      
 920 
     | 
    
         
            +
                old_implicit_order_column = Topic.implicit_order_column
         
     | 
| 
      
 921 
     | 
    
         
            +
                Topic.implicit_order_column = "title"
         
     | 
| 
      
 922 
     | 
    
         
            +
             
     | 
| 
      
 923 
     | 
    
         
            +
                assert_equal topics(:fifth), Topic.first
         
     | 
| 
      
 924 
     | 
    
         
            +
                assert_equal topics(:third), Topic.last
         
     | 
| 
      
 925 
     | 
    
         
            +
             
     | 
| 
      
 926 
     | 
    
         
            +
                c = Topic.connection
         
     | 
| 
      
 927 
     | 
    
         
            +
                assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
         
     | 
| 
      
 928 
     | 
    
         
            +
                  Topic.last
         
     | 
| 
      
 929 
     | 
    
         
            +
                }
         
     | 
| 
      
 930 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 931 
     | 
    
         
            +
                Topic.implicit_order_column = old_implicit_order_column
         
     | 
| 
      
 932 
     | 
    
         
            +
              end
         
     | 
| 
      
 933 
     | 
    
         
            +
             
     | 
| 
      
 934 
     | 
    
         
            +
              # Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
         
     | 
| 
      
 935 
     | 
    
         
            +
              coerce_tests! :test_implicit_order_set_to_primary_key
         
     | 
| 
      
 936 
     | 
    
         
            +
              def test_implicit_order_set_to_primary_key_coerced
         
     | 
| 
      
 937 
     | 
    
         
            +
                old_implicit_order_column = Topic.implicit_order_column
         
     | 
| 
      
 938 
     | 
    
         
            +
                Topic.implicit_order_column = "id"
         
     | 
| 
      
 939 
     | 
    
         
            +
             
     | 
| 
      
 940 
     | 
    
         
            +
                c = Topic.connection
         
     | 
| 
      
 941 
     | 
    
         
            +
                assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
         
     | 
| 
      
 942 
     | 
    
         
            +
                  Topic.last
         
     | 
| 
      
 943 
     | 
    
         
            +
                }
         
     | 
| 
      
 944 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 945 
     | 
    
         
            +
                Topic.implicit_order_column = old_implicit_order_column
         
     | 
| 
      
 946 
     | 
    
         
            +
              end
         
     | 
| 
      
 947 
     | 
    
         
            +
             
     | 
| 
      
 948 
     | 
    
         
            +
              # Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
         
     | 
| 
      
 949 
     | 
    
         
            +
              coerce_tests! :test_implicit_order_for_model_without_primary_key
         
     | 
| 
      
 950 
     | 
    
         
            +
              def test_implicit_order_for_model_without_primary_key_coerced
         
     | 
| 
      
 951 
     | 
    
         
            +
                old_implicit_order_column = NonPrimaryKey.implicit_order_column
         
     | 
| 
      
 952 
     | 
    
         
            +
                NonPrimaryKey.implicit_order_column = "created_at"
         
     | 
| 
      
 953 
     | 
    
         
            +
             
     | 
| 
      
 954 
     | 
    
         
            +
                c = NonPrimaryKey.connection
         
     | 
| 
      
 955 
     | 
    
         
            +
             
     | 
| 
      
 956 
     | 
    
         
            +
                assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
         
     | 
| 
      
 957 
     | 
    
         
            +
                  NonPrimaryKey.last
         
     | 
| 
      
 958 
     | 
    
         
            +
                }
         
     | 
| 
      
 959 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 960 
     | 
    
         
            +
                NonPrimaryKey.implicit_order_column = old_implicit_order_column
         
     | 
| 
      
 961 
     | 
    
         
            +
              end
         
     | 
| 
      
 962 
     | 
    
         
            +
             
     | 
| 
      
 963 
     | 
    
         
            +
              # SQL Server is unable to use aliased SELECT in the HAVING clause.
         
     | 
| 
      
 964 
     | 
    
         
            +
              coerce_tests! :test_include_on_unloaded_relation_with_having_referencing_aliased_select
         
     | 
| 
       701 
965 
     | 
    
         
             
            end
         
     | 
| 
       702 
966 
     | 
    
         | 
| 
       703 
967 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
         @@ -929,7 +1193,14 @@ class RelationTest < ActiveRecord::TestCase 
     | 
|
| 
       929 
1193 
     | 
    
         
             
              coerce_tests! :test_reorder_with_first
         
     | 
| 
       930 
1194 
     | 
    
         
             
              def test_reorder_with_first_coerced
         
     | 
| 
       931 
1195 
     | 
    
         
             
                sql_log = capture_sql do
         
     | 
| 
       932 
     | 
    
         
            -
                   
     | 
| 
      
 1196 
     | 
    
         
            +
                  message = <<~MSG.squish
         
     | 
| 
      
 1197 
     | 
    
         
            +
                    `.reorder(nil)` with `.first` / `.first!` no longer
         
     | 
| 
      
 1198 
     | 
    
         
            +
                    takes non-deterministic result in Rails 6.2.
         
     | 
| 
      
 1199 
     | 
    
         
            +
                    To continue taking non-deterministic result, use `.take` / `.take!` instead.
         
     | 
| 
      
 1200 
     | 
    
         
            +
                  MSG
         
     | 
| 
      
 1201 
     | 
    
         
            +
                  assert_deprecated(message) do
         
     | 
| 
      
 1202 
     | 
    
         
            +
                    assert Post.order(:title).reorder(nil).first
         
     | 
| 
      
 1203 
     | 
    
         
            +
                  end
         
     | 
| 
       933 
1204 
     | 
    
         
             
                end
         
     | 
| 
       934 
1205 
     | 
    
         
             
                assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
         
     | 
| 
       935 
1206 
     | 
    
         
             
                assert sql_log.all?  { |sql| /order by \[posts\]\.\[id\]/i.match?(sql) }, "default ORDER BY ID was not used in the query: #{sql_log}"
         
     | 
| 
         @@ -982,6 +1253,31 @@ class RelationTest < ActiveRecord::TestCase 
     | 
|
| 
       982 
1253 
     | 
    
         
             
              end
         
     | 
| 
       983 
1254 
     | 
    
         
             
            end
         
     | 
| 
       984 
1255 
     | 
    
         | 
| 
      
 1256 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 1257 
     | 
    
         
            +
              class RelationTest < ActiveRecord::TestCase
         
     | 
| 
      
 1258 
     | 
    
         
            +
                # Skipping this test. SQL Server doesn't support optimizer hint as comments
         
     | 
| 
      
 1259 
     | 
    
         
            +
                coerce_tests! :test_relation_with_optimizer_hints_filters_sql_comment_delimiters
         
     | 
| 
      
 1260 
     | 
    
         
            +
             
     | 
| 
      
 1261 
     | 
    
         
            +
                coerce_tests! :test_does_not_duplicate_optimizer_hints_on_merge
         
     | 
| 
      
 1262 
     | 
    
         
            +
                def test_does_not_duplicate_optimizer_hints_on_merge_coerced
         
     | 
| 
      
 1263 
     | 
    
         
            +
                  escaped_table = Post.connection.quote_table_name("posts")
         
     | 
| 
      
 1264 
     | 
    
         
            +
                  expected = "SELECT #{escaped_table}.* FROM #{escaped_table} OPTION (OMGHINT)"
         
     | 
| 
      
 1265 
     | 
    
         
            +
                  query = Post.optimizer_hints("OMGHINT").merge(Post.optimizer_hints("OMGHINT")).to_sql
         
     | 
| 
      
 1266 
     | 
    
         
            +
                  assert_equal expected, query
         
     | 
| 
      
 1267 
     | 
    
         
            +
                end
         
     | 
| 
      
 1268 
     | 
    
         
            +
             
     | 
| 
      
 1269 
     | 
    
         
            +
                # Original Rails test fails on Windows CI because the dump file was not being binary read.
         
     | 
| 
      
 1270 
     | 
    
         
            +
                coerce_tests! :test_marshal_load_legacy_relation
         
     | 
| 
      
 1271 
     | 
    
         
            +
                def test_marshal_load_legacy_relation_coerced
         
     | 
| 
      
 1272 
     | 
    
         
            +
                  path = File.expand_path(
         
     | 
| 
      
 1273 
     | 
    
         
            +
                    "support/marshal_compatibility_fixtures/legacy_relation.dump",
         
     | 
| 
      
 1274 
     | 
    
         
            +
                    ARTest::SQLServer.root_activerecord_test
         
     | 
| 
      
 1275 
     | 
    
         
            +
                  )
         
     | 
| 
      
 1276 
     | 
    
         
            +
                  assert_equal 11, Marshal.load(File.binread(path)).size
         
     | 
| 
      
 1277 
     | 
    
         
            +
                end
         
     | 
| 
      
 1278 
     | 
    
         
            +
              end
         
     | 
| 
      
 1279 
     | 
    
         
            +
            end
         
     | 
| 
      
 1280 
     | 
    
         
            +
             
     | 
| 
       985 
1281 
     | 
    
         
             
            require "models/post"
         
     | 
| 
       986 
1282 
     | 
    
         
             
            class SanitizeTest < ActiveRecord::TestCase
         
     | 
| 
       987 
1283 
     | 
    
         
             
              # Use nvarchar string (N'') in assert
         
     | 
| 
         @@ -1225,6 +1521,7 @@ module ActiveRecord 
     | 
|
| 
       1225 
1521 
     | 
    
         | 
| 
       1226 
1522 
     | 
    
         
             
                  original_test_statement_cache_values_differ
         
     | 
| 
       1227 
1523 
     | 
    
         
             
                ensure
         
     | 
| 
      
 1524 
     | 
    
         
            +
                  Book.where(author_id: nil, name: 'my book').delete_all
         
     | 
| 
       1228 
1525 
     | 
    
         
             
                  Book.connection.add_index(:books, [:author_id, :name], unique: true)
         
     | 
| 
       1229 
1526 
     | 
    
         
             
                end
         
     | 
| 
       1230 
1527 
     | 
    
         
             
              end
         
     | 
| 
         @@ -1233,8 +1530,43 @@ end 
     | 
|
| 
       1233 
1530 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       1234 
1531 
     | 
    
         
             
              module ConnectionAdapters
         
     | 
| 
       1235 
1532 
     | 
    
         
             
                class SchemaCacheTest < ActiveRecord::TestCase
         
     | 
| 
      
 1533 
     | 
    
         
            +
                  # Tests fail on Windows AppVeyor CI with 'Permission denied' error when renaming file during `File.atomic_write` call.
         
     | 
| 
      
 1534 
     | 
    
         
            +
                  coerce_tests! :test_yaml_dump_and_load, :test_yaml_dump_and_load_with_gzip if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
         
     | 
| 
      
 1535 
     | 
    
         
            +
             
     | 
| 
      
 1536 
     | 
    
         
            +
                  # Ruby 2.5 and 2.6 have issues to marshal Time before 1900. 2012.sql has one column with default value 1753
         
     | 
| 
      
 1537 
     | 
    
         
            +
                  coerce_tests! :test_marshal_dump_and_load_with_gzip, :test_marshal_dump_and_load_via_disk
         
     | 
| 
      
 1538 
     | 
    
         
            +
             
     | 
| 
      
 1539 
     | 
    
         
            +
                  # Tests fail on Windows AppVeyor CI with 'Permission denied' error when renaming file during `File.atomic_write` call.
         
     | 
| 
      
 1540 
     | 
    
         
            +
                  unless RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
         
     | 
| 
      
 1541 
     | 
    
         
            +
                    def test_marshal_dump_and_load_with_gzip_coerced
         
     | 
| 
      
 1542 
     | 
    
         
            +
                      with_marshable_time_defaults { original_test_marshal_dump_and_load_with_gzip }
         
     | 
| 
      
 1543 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1544 
     | 
    
         
            +
                    def test_marshal_dump_and_load_via_disk_coerced
         
     | 
| 
      
 1545 
     | 
    
         
            +
                      with_marshable_time_defaults { original_test_marshal_dump_and_load_via_disk }
         
     | 
| 
      
 1546 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1547 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1548 
     | 
    
         
            +
             
     | 
| 
       1236 
1549 
     | 
    
         
             
                  private
         
     | 
| 
       1237 
1550 
     | 
    
         | 
| 
      
 1551 
     | 
    
         
            +
                  def with_marshable_time_defaults
         
     | 
| 
      
 1552 
     | 
    
         
            +
                    # Detect problems
         
     | 
| 
      
 1553 
     | 
    
         
            +
                    if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7")
         
     | 
| 
      
 1554 
     | 
    
         
            +
                      column = @connection.columns(:sst_datatypes).find { |c| c.name == "datetime" }
         
     | 
| 
      
 1555 
     | 
    
         
            +
                      current_default = column.default if column.default.is_a?(Time) && column.default.year < 1900
         
     | 
| 
      
 1556 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1557 
     | 
    
         
            +
             
     | 
| 
      
 1558 
     | 
    
         
            +
                    # Correct problems
         
     | 
| 
      
 1559 
     | 
    
         
            +
                    if current_default.present?
         
     | 
| 
      
 1560 
     | 
    
         
            +
                      @connection.change_column_default(:sst_datatypes, :datetime, current_default.dup.change(year: 1900))
         
     | 
| 
      
 1561 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1562 
     | 
    
         
            +
             
     | 
| 
      
 1563 
     | 
    
         
            +
                    # Run original test
         
     | 
| 
      
 1564 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 1565 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 1566 
     | 
    
         
            +
                    # Revert changes
         
     | 
| 
      
 1567 
     | 
    
         
            +
                    @connection.change_column_default(:sst_datatypes, :datetime, current_default) if current_default.present?
         
     | 
| 
      
 1568 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1569 
     | 
    
         
            +
             
     | 
| 
       1238 
1570 
     | 
    
         
             
                  # We need to give the full path for this to work.
         
     | 
| 
       1239 
1571 
     | 
    
         
             
                  def schema_dump_path
         
     | 
| 
       1240 
1572 
     | 
    
         
             
                    File.join ARTest::SQLServer.root_activerecord, "test/assets/schema_dump_5_1.yml"
         
     | 
| 
         @@ -1243,23 +1575,26 @@ module ActiveRecord 
     | 
|
| 
       1243 
1575 
     | 
    
         
             
              end
         
     | 
| 
       1244 
1576 
     | 
    
         
             
            end
         
     | 
| 
       1245 
1577 
     | 
    
         | 
| 
      
 1578 
     | 
    
         
            +
            require "models/post"
         
     | 
| 
      
 1579 
     | 
    
         
            +
            require "models/comment"
         
     | 
| 
       1246 
1580 
     | 
    
         
             
            class UnsafeRawSqlTest < ActiveRecord::TestCase
         
     | 
| 
      
 1581 
     | 
    
         
            +
              fixtures :posts
         
     | 
| 
      
 1582 
     | 
    
         
            +
             
     | 
| 
       1247 
1583 
     | 
    
         
             
              # Use LEN() vs length() function.
         
     | 
| 
       1248 
1584 
     | 
    
         
             
              coerce_tests! %r{order: always allows Arel}
         
     | 
| 
       1249 
1585 
     | 
    
         
             
              test "order: always allows Arel" do
         
     | 
| 
       1250 
     | 
    
         
            -
                 
     | 
| 
       1251 
     | 
    
         
            -
                ids_disabled = with_unsafe_raw_sql_disabled   { Post.order(Arel.sql("len(title)")).pluck(:title) }
         
     | 
| 
      
 1586 
     | 
    
         
            +
                titles = Post.order(Arel.sql("len(title)")).pluck(:title)
         
     | 
| 
       1252 
1587 
     | 
    
         | 
| 
       1253 
     | 
    
         
            -
                 
     | 
| 
      
 1588 
     | 
    
         
            +
                assert_not_empty titles
         
     | 
| 
       1254 
1589 
     | 
    
         
             
              end
         
     | 
| 
       1255 
1590 
     | 
    
         | 
| 
       1256 
1591 
     | 
    
         
             
              # Use LEN() vs length() function.
         
     | 
| 
       1257 
1592 
     | 
    
         
             
              coerce_tests! %r{pluck: always allows Arel}
         
     | 
| 
       1258 
1593 
     | 
    
         
             
              test "pluck: always allows Arel" do
         
     | 
| 
       1259 
     | 
    
         
            -
                 
     | 
| 
       1260 
     | 
    
         
            -
                 
     | 
| 
      
 1594 
     | 
    
         
            +
                excepted_values = Post.includes(:comments).pluck(:title).map { |title| [title, title.size] }
         
     | 
| 
      
 1595 
     | 
    
         
            +
                values = Post.includes(:comments).pluck(:title, Arel.sql("len(title)"))
         
     | 
| 
       1261 
1596 
     | 
    
         | 
| 
       1262 
     | 
    
         
            -
                assert_equal  
     | 
| 
      
 1597 
     | 
    
         
            +
                assert_equal excepted_values, values
         
     | 
| 
       1263 
1598 
     | 
    
         
             
              end
         
     | 
| 
       1264 
1599 
     | 
    
         | 
| 
       1265 
1600 
     | 
    
         
             
              # Use LEN() vs length() function.
         
     | 
| 
         @@ -1267,11 +1602,73 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase 
     | 
|
| 
       1267 
1602 
     | 
    
         
             
              test "order: allows valid Array arguments" do
         
     | 
| 
       1268 
1603 
     | 
    
         
             
                ids_expected = Post.order(Arel.sql("author_id, len(title)")).pluck(:id)
         
     | 
| 
       1269 
1604 
     | 
    
         | 
| 
       1270 
     | 
    
         
            -
                 
     | 
| 
       1271 
     | 
    
         
            -
             
     | 
| 
      
 1605 
     | 
    
         
            +
                ids = Post.order(["author_id", "len(title)"]).pluck(:id)
         
     | 
| 
      
 1606 
     | 
    
         
            +
             
     | 
| 
      
 1607 
     | 
    
         
            +
                assert_equal ids_expected, ids
         
     | 
| 
      
 1608 
     | 
    
         
            +
              end
         
     | 
| 
      
 1609 
     | 
    
         
            +
             
     | 
| 
      
 1610 
     | 
    
         
            +
              test "order: allows string column names that are quoted" do
         
     | 
| 
      
 1611 
     | 
    
         
            +
                ids_expected = Post.order(Arel.sql("id")).pluck(:id)
         
     | 
| 
      
 1612 
     | 
    
         
            +
             
     | 
| 
      
 1613 
     | 
    
         
            +
                ids = Post.order("[id]").pluck(:id)
         
     | 
| 
      
 1614 
     | 
    
         
            +
             
     | 
| 
      
 1615 
     | 
    
         
            +
                assert_equal ids_expected, ids
         
     | 
| 
      
 1616 
     | 
    
         
            +
              end
         
     | 
| 
      
 1617 
     | 
    
         
            +
             
     | 
| 
      
 1618 
     | 
    
         
            +
              test "order: allows string column names that are quoted with table" do
         
     | 
| 
      
 1619 
     | 
    
         
            +
                ids_expected = Post.order(Arel.sql("id")).pluck(:id)
         
     | 
| 
      
 1620 
     | 
    
         
            +
             
     | 
| 
      
 1621 
     | 
    
         
            +
                ids = Post.order("[posts].[id]").pluck(:id)
         
     | 
| 
      
 1622 
     | 
    
         
            +
             
     | 
| 
      
 1623 
     | 
    
         
            +
                assert_equal ids_expected, ids
         
     | 
| 
      
 1624 
     | 
    
         
            +
              end
         
     | 
| 
      
 1625 
     | 
    
         
            +
             
     | 
| 
      
 1626 
     | 
    
         
            +
              test "order: allows string column names that are quoted with table and user" do
         
     | 
| 
      
 1627 
     | 
    
         
            +
                ids_expected = Post.order(Arel.sql("id")).pluck(:id)
         
     | 
| 
      
 1628 
     | 
    
         
            +
             
     | 
| 
      
 1629 
     | 
    
         
            +
                ids = Post.order("[dbo].[posts].[id]").pluck(:id)
         
     | 
| 
       1272 
1630 
     | 
    
         | 
| 
       1273 
     | 
    
         
            -
                assert_equal ids_expected,  
     | 
| 
       1274 
     | 
    
         
            -
             
     | 
| 
      
 1631 
     | 
    
         
            +
                assert_equal ids_expected, ids
         
     | 
| 
      
 1632 
     | 
    
         
            +
              end
         
     | 
| 
      
 1633 
     | 
    
         
            +
             
     | 
| 
      
 1634 
     | 
    
         
            +
              test "order: allows string column names that are quoted with table, user and database" do
         
     | 
| 
      
 1635 
     | 
    
         
            +
                ids_expected = Post.order(Arel.sql("id")).pluck(:id)
         
     | 
| 
      
 1636 
     | 
    
         
            +
             
     | 
| 
      
 1637 
     | 
    
         
            +
                ids = Post.order("[activerecord_unittest].[dbo].[posts].[id]").pluck(:id)
         
     | 
| 
      
 1638 
     | 
    
         
            +
             
     | 
| 
      
 1639 
     | 
    
         
            +
                assert_equal ids_expected, ids
         
     | 
| 
      
 1640 
     | 
    
         
            +
              end
         
     | 
| 
      
 1641 
     | 
    
         
            +
             
     | 
| 
      
 1642 
     | 
    
         
            +
              test "pluck: allows string column name that are quoted" do
         
     | 
| 
      
 1643 
     | 
    
         
            +
                titles_expected = Post.pluck(Arel.sql("title"))
         
     | 
| 
      
 1644 
     | 
    
         
            +
             
     | 
| 
      
 1645 
     | 
    
         
            +
                titles = Post.pluck("[title]")
         
     | 
| 
      
 1646 
     | 
    
         
            +
             
     | 
| 
      
 1647 
     | 
    
         
            +
                assert_equal titles_expected, titles
         
     | 
| 
      
 1648 
     | 
    
         
            +
              end
         
     | 
| 
      
 1649 
     | 
    
         
            +
             
     | 
| 
      
 1650 
     | 
    
         
            +
              test "pluck: allows string column name that are quoted with table" do
         
     | 
| 
      
 1651 
     | 
    
         
            +
                titles_expected = Post.pluck(Arel.sql("title"))
         
     | 
| 
      
 1652 
     | 
    
         
            +
             
     | 
| 
      
 1653 
     | 
    
         
            +
                titles = Post.pluck("[posts].[title]")
         
     | 
| 
      
 1654 
     | 
    
         
            +
             
     | 
| 
      
 1655 
     | 
    
         
            +
                assert_equal titles_expected, titles
         
     | 
| 
      
 1656 
     | 
    
         
            +
              end
         
     | 
| 
      
 1657 
     | 
    
         
            +
             
     | 
| 
      
 1658 
     | 
    
         
            +
              test "pluck: allows string column name that are quoted with table and user" do
         
     | 
| 
      
 1659 
     | 
    
         
            +
                titles_expected = Post.pluck(Arel.sql("title"))
         
     | 
| 
      
 1660 
     | 
    
         
            +
             
     | 
| 
      
 1661 
     | 
    
         
            +
                titles = Post.pluck("[dbo].[posts].[title]")
         
     | 
| 
      
 1662 
     | 
    
         
            +
             
     | 
| 
      
 1663 
     | 
    
         
            +
                assert_equal titles_expected, titles
         
     | 
| 
      
 1664 
     | 
    
         
            +
              end
         
     | 
| 
      
 1665 
     | 
    
         
            +
             
     | 
| 
      
 1666 
     | 
    
         
            +
              test "pluck: allows string column name that are quoted with table, user and database" do
         
     | 
| 
      
 1667 
     | 
    
         
            +
                titles_expected = Post.pluck(Arel.sql("title"))
         
     | 
| 
      
 1668 
     | 
    
         
            +
             
     | 
| 
      
 1669 
     | 
    
         
            +
                titles = Post.pluck("[activerecord_unittest].[dbo].[posts].[title]")
         
     | 
| 
      
 1670 
     | 
    
         
            +
             
     | 
| 
      
 1671 
     | 
    
         
            +
                assert_equal titles_expected, titles
         
     | 
| 
       1275 
1672 
     | 
    
         
             
              end
         
     | 
| 
       1276 
1673 
     | 
    
         
             
            end
         
     | 
| 
       1277 
1674 
     | 
    
         | 
| 
         @@ -1313,6 +1710,25 @@ class RelationMergingTest < ActiveRecord::TestCase 
     | 
|
| 
       1313 
1710 
     | 
    
         
             
                relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
         
     | 
| 
       1314 
1711 
     | 
    
         
             
                assert_equal ["title LIKE N'%suffix'"], relation.order_values
         
     | 
| 
       1315 
1712 
     | 
    
         
             
              end
         
     | 
| 
      
 1713 
     | 
    
         
            +
             
     | 
| 
      
 1714 
     | 
    
         
            +
              # Same as original but change first regexp to match sp_executesql binding syntax
         
     | 
| 
      
 1715 
     | 
    
         
            +
              coerce_tests! :test_merge_doesnt_duplicate_same_clauses
         
     | 
| 
      
 1716 
     | 
    
         
            +
              def test_merge_doesnt_duplicate_same_clauses_coerced
         
     | 
| 
      
 1717 
     | 
    
         
            +
                david, mary, bob = authors(:david, :mary, :bob)
         
     | 
| 
      
 1718 
     | 
    
         
            +
             
     | 
| 
      
 1719 
     | 
    
         
            +
                non_mary_and_bob = Author.where.not(id: [mary, bob])
         
     | 
| 
      
 1720 
     | 
    
         
            +
             
     | 
| 
      
 1721 
     | 
    
         
            +
                author_id = Author.connection.quote_table_name("authors.id")
         
     | 
| 
      
 1722 
     | 
    
         
            +
                assert_sql(/WHERE #{Regexp.escape(author_id)} NOT IN \((@\d), \g<1>\)'/) do
         
     | 
| 
      
 1723 
     | 
    
         
            +
                  assert_equal [david], non_mary_and_bob.merge(non_mary_and_bob)
         
     | 
| 
      
 1724 
     | 
    
         
            +
                end
         
     | 
| 
      
 1725 
     | 
    
         
            +
             
     | 
| 
      
 1726 
     | 
    
         
            +
                only_david = Author.where("#{author_id} IN (?)", david)
         
     | 
| 
      
 1727 
     | 
    
         
            +
             
     | 
| 
      
 1728 
     | 
    
         
            +
                assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \(1\)\)\z/) do
         
     | 
| 
      
 1729 
     | 
    
         
            +
                  assert_equal [david], only_david.merge(only_david)
         
     | 
| 
      
 1730 
     | 
    
         
            +
                end
         
     | 
| 
      
 1731 
     | 
    
         
            +
              end
         
     | 
| 
       1316 
1732 
     | 
    
         
             
            end
         
     | 
| 
       1317 
1733 
     | 
    
         | 
| 
       1318 
1734 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
         @@ -1333,6 +1749,7 @@ class EnumTest < ActiveRecord::TestCase 
     | 
|
| 
       1333 
1749 
     | 
    
         | 
| 
       1334 
1750 
     | 
    
         
             
                send(:'original_enums are distinct per class')
         
     | 
| 
       1335 
1751 
     | 
    
         
             
              ensure
         
     | 
| 
      
 1752 
     | 
    
         
            +
                Book.where(author_id: nil, name: nil).delete_all
         
     | 
| 
       1336 
1753 
     | 
    
         
             
                Book.connection.add_index(:books, [:author_id, :name], unique: true)
         
     | 
| 
       1337 
1754 
     | 
    
         
             
              end
         
     | 
| 
       1338 
1755 
     | 
    
         | 
| 
         @@ -1343,6 +1760,7 @@ class EnumTest < ActiveRecord::TestCase 
     | 
|
| 
       1343 
1760 
     | 
    
         | 
| 
       1344 
1761 
     | 
    
         
             
                send(:'original_creating new objects with enum scopes')
         
     | 
| 
       1345 
1762 
     | 
    
         
             
              ensure
         
     | 
| 
      
 1763 
     | 
    
         
            +
                Book.where(author_id: nil, name: nil).delete_all
         
     | 
| 
       1346 
1764 
     | 
    
         
             
                Book.connection.add_index(:books, [:author_id, :name], unique: true)
         
     | 
| 
       1347 
1765 
     | 
    
         
             
              end
         
     | 
| 
       1348 
1766 
     | 
    
         | 
| 
         @@ -1353,6 +1771,7 @@ class EnumTest < ActiveRecord::TestCase 
     | 
|
| 
       1353 
1771 
     | 
    
         | 
| 
       1354 
1772 
     | 
    
         
             
                send(:'original_enums are inheritable')
         
     | 
| 
       1355 
1773 
     | 
    
         
             
              ensure
         
     | 
| 
      
 1774 
     | 
    
         
            +
                Book.where(author_id: nil, name: nil).delete_all
         
     | 
| 
       1356 
1775 
     | 
    
         
             
                Book.connection.add_index(:books, [:author_id, :name], unique: true)
         
     | 
| 
       1357 
1776 
     | 
    
         
             
              end
         
     | 
| 
       1358 
1777 
     | 
    
         | 
| 
         @@ -1363,6 +1782,7 @@ class EnumTest < ActiveRecord::TestCase 
     | 
|
| 
       1363 
1782 
     | 
    
         | 
| 
       1364 
1783 
     | 
    
         
             
                send(:'original_declare multiple enums at a time')
         
     | 
| 
       1365 
1784 
     | 
    
         
             
              ensure
         
     | 
| 
      
 1785 
     | 
    
         
            +
                Book.where(author_id: nil, name: nil).delete_all
         
     | 
| 
       1366 
1786 
     | 
    
         
             
                Book.connection.add_index(:books, [:author_id, :name], unique: true)
         
     | 
| 
       1367 
1787 
     | 
    
         
             
              end
         
     | 
| 
       1368 
1788 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1400,6 +1820,8 @@ end 
     | 
|
| 
       1400 
1820 
     | 
    
         | 
| 
       1401 
1821 
     | 
    
         
             
            require "models/citation"
         
     | 
| 
       1402 
1822 
     | 
    
         
             
            class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
         
     | 
| 
      
 1823 
     | 
    
         
            +
              fixtures :citations
         
     | 
| 
      
 1824 
     | 
    
         
            +
             
     | 
| 
       1403 
1825 
     | 
    
         
             
              # Original Rails test fails with SQL Server error message "The query processor ran out of internal resources and
         
     | 
| 
       1404 
1826 
     | 
    
         
             
              # could not produce a query plan". This error goes away if you change database compatibility level to 110 (SQL 2012)
         
     | 
| 
       1405 
1827 
     | 
    
         
             
              # (see https://www.mssqltips.com/sqlservertip/5279/sql-server-error-query-processor-ran-out-of-internal-resources-and-could-not-produce-a-query-plan/).
         
     | 
| 
         @@ -1407,14 +1829,14 @@ class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase 
     | 
|
| 
       1407 
1829 
     | 
    
         
             
              # unprepared statement is used if the number of values exceeds the adapter's `bind_params_length`. The coerced test
         
     | 
| 
       1408 
1830 
     | 
    
         
             
              # still does this as there will be 32,768 remaining citation records in the database and the `bind_params_length` of
         
     | 
| 
       1409 
1831 
     | 
    
         
             
              # adapter is 2,098.
         
     | 
| 
       1410 
     | 
    
         
            -
              coerce_tests! : 
     | 
| 
       1411 
     | 
    
         
            -
              def  
     | 
| 
      
 1832 
     | 
    
         
            +
              coerce_tests! :test_eager_loading_too_many_ids
         
     | 
| 
      
 1833 
     | 
    
         
            +
              def test_eager_loading_too_many_ids_coerced
         
     | 
| 
       1412 
1834 
     | 
    
         
             
                # Remove excess records.
         
     | 
| 
       1413 
1835 
     | 
    
         
             
                Citation.limit(32768).order(id: :desc).delete_all
         
     | 
| 
       1414 
1836 
     | 
    
         | 
| 
       1415 
1837 
     | 
    
         
             
                # Perform test
         
     | 
| 
       1416 
1838 
     | 
    
         
             
                citation_count = Citation.count
         
     | 
| 
       1417 
     | 
    
         
            -
                assert_sql(/WHERE \ 
     | 
| 
      
 1839 
     | 
    
         
            +
                assert_sql(/WHERE \[citations\]\.\[id\] IN \(0, 1/) do
         
     | 
| 
       1418 
1840 
     | 
    
         
             
                  assert_equal citation_count, Citation.eager_load(:citations).offset(0).size
         
     | 
| 
       1419 
1841 
     | 
    
         
             
                end
         
     | 
| 
       1420 
1842 
     | 
    
         
             
              end
         
     | 
| 
         @@ -1426,6 +1848,14 @@ class LogSubscriberTest < ActiveRecord::TestCase 
     | 
|
| 
       1426 
1848 
     | 
    
         
             
              def test_vebose_query_logs_coerced
         
     | 
| 
       1427 
1849 
     | 
    
         
             
                original_test_vebose_query_logs
         
     | 
| 
       1428 
1850 
     | 
    
         
             
              end
         
     | 
| 
      
 1851 
     | 
    
         
            +
             
     | 
| 
      
 1852 
     | 
    
         
            +
              # Bindings logged slightly differently.
         
     | 
| 
      
 1853 
     | 
    
         
            +
              coerce_tests! :test_where_in_binds_logging_include_attribute_names
         
     | 
| 
      
 1854 
     | 
    
         
            +
              def test_where_in_binds_logging_include_attribute_names_coerced
         
     | 
| 
      
 1855 
     | 
    
         
            +
                Developer.where(id: [1, 2, 3, 4, 5]).load
         
     | 
| 
      
 1856 
     | 
    
         
            +
                wait
         
     | 
| 
      
 1857 
     | 
    
         
            +
                assert_match(%{@0 = 1, @1 = 2, @2 = 3, @3 = 4, @4 = 5  [["id", nil], ["id", nil], ["id", nil], ["id", nil], ["id", nil]]}, @logger.logged(:debug).last)
         
     | 
| 
      
 1858 
     | 
    
         
            +
              end
         
     | 
| 
       1429 
1859 
     | 
    
         
             
            end
         
     | 
| 
       1430 
1860 
     | 
    
         | 
| 
       1431 
1861 
     | 
    
         
             
            class ActiveRecordSchemaTest < ActiveRecord::TestCase
         
     | 
| 
         @@ -1437,22 +1867,125 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase 
     | 
|
| 
       1437 
1867 
     | 
    
         
             
              end
         
     | 
| 
       1438 
1868 
     | 
    
         
             
            end
         
     | 
| 
       1439 
1869 
     | 
    
         | 
| 
       1440 
     | 
    
         
            -
             
     | 
| 
       1441 
     | 
    
         
            -
               
     | 
| 
       1442 
     | 
    
         
            -
             
     | 
| 
       1443 
     | 
    
         
            -
             
     | 
| 
       1444 
     | 
    
         
            -
             
     | 
| 
      
 1870 
     | 
    
         
            +
            class ReloadModelsTest < ActiveRecord::TestCase
         
     | 
| 
      
 1871 
     | 
    
         
            +
              # Skip test on Windows. The number of arguments passed to `IO.popen` in
         
     | 
| 
      
 1872 
     | 
    
         
            +
              # `activesupport/lib/active_support/testing/isolation.rb` exceeds what Windows can handle.
         
     | 
| 
      
 1873 
     | 
    
         
            +
              coerce_tests! :test_has_one_with_reload if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
         
     | 
| 
      
 1874 
     | 
    
         
            +
            end
         
     | 
| 
      
 1875 
     | 
    
         
            +
             
     | 
| 
      
 1876 
     | 
    
         
            +
            require "models/post"
         
     | 
| 
      
 1877 
     | 
    
         
            +
            class AnnotateTest < ActiveRecord::TestCase
         
     | 
| 
      
 1878 
     | 
    
         
            +
              # Same as original coerced test except our SQL starts with `EXEC sp_executesql`.
         
     | 
| 
      
 1879 
     | 
    
         
            +
              # TODO: Remove coerce after Rails 7 (see https://github.com/rails/rails/pull/42027)
         
     | 
| 
      
 1880 
     | 
    
         
            +
              coerce_tests! :test_annotate_wraps_content_in_an_inline_comment
         
     | 
| 
      
 1881 
     | 
    
         
            +
              def test_annotate_wraps_content_in_an_inline_comment_coerced
         
     | 
| 
      
 1882 
     | 
    
         
            +
                quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
         
     | 
| 
      
 1883 
     | 
    
         
            +
             
     | 
| 
      
 1884 
     | 
    
         
            +
                assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
         
     | 
| 
      
 1885 
     | 
    
         
            +
                  posts = Post.select(:id).annotate("foo")
         
     | 
| 
      
 1886 
     | 
    
         
            +
                  assert posts.first
         
     | 
| 
      
 1887 
     | 
    
         
            +
                end
         
     | 
| 
      
 1888 
     | 
    
         
            +
              end
         
     | 
| 
      
 1889 
     | 
    
         
            +
             
     | 
| 
      
 1890 
     | 
    
         
            +
              # Same as original coerced test except our SQL starts with `EXEC sp_executesql`.
         
     | 
| 
      
 1891 
     | 
    
         
            +
              # TODO: Remove coerce after Rails 7 (see https://github.com/rails/rails/pull/42027)
         
     | 
| 
      
 1892 
     | 
    
         
            +
              coerce_tests! :test_annotate_is_sanitized
         
     | 
| 
      
 1893 
     | 
    
         
            +
              def test_annotate_is_sanitized_coerced
         
     | 
| 
      
 1894 
     | 
    
         
            +
                quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
         
     | 
| 
      
 1895 
     | 
    
         
            +
             
     | 
| 
      
 1896 
     | 
    
         
            +
                assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
         
     | 
| 
      
 1897 
     | 
    
         
            +
                  posts = Post.select(:id).annotate("*/foo/*")
         
     | 
| 
      
 1898 
     | 
    
         
            +
                  assert posts.first
         
     | 
| 
      
 1899 
     | 
    
         
            +
                end
         
     | 
| 
      
 1900 
     | 
    
         
            +
             
     | 
| 
      
 1901 
     | 
    
         
            +
                assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
         
     | 
| 
      
 1902 
     | 
    
         
            +
                  posts = Post.select(:id).annotate("**//foo//**")
         
     | 
| 
      
 1903 
     | 
    
         
            +
                  assert posts.first
         
     | 
| 
      
 1904 
     | 
    
         
            +
                end
         
     | 
| 
      
 1905 
     | 
    
         
            +
             
     | 
| 
      
 1906 
     | 
    
         
            +
                assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/ /\* bar \*/}i) do
         
     | 
| 
      
 1907 
     | 
    
         
            +
                  posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
         
     | 
| 
      
 1908 
     | 
    
         
            +
                  assert posts.first
         
     | 
| 
      
 1909 
     | 
    
         
            +
                end
         
     | 
| 
      
 1910 
     | 
    
         
            +
             
     | 
| 
      
 1911 
     | 
    
         
            +
                assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \+ MAX_EXECUTION_TIME\(1\) \*/}i) do
         
     | 
| 
      
 1912 
     | 
    
         
            +
                  posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)")
         
     | 
| 
      
 1913 
     | 
    
         
            +
                  assert posts.first
         
     | 
| 
       1445 
1914 
     | 
    
         
             
                end
         
     | 
| 
       1446 
1915 
     | 
    
         
             
              end
         
     | 
| 
       1447 
1916 
     | 
    
         
             
            end
         
     | 
| 
       1448 
1917 
     | 
    
         | 
| 
       1449 
     | 
    
         
            -
            class  
     | 
| 
       1450 
     | 
    
         
            -
               
     | 
| 
       1451 
     | 
    
         
            -
             
     | 
| 
      
 1918 
     | 
    
         
            +
            class MarshalSerializationTest < ActiveRecord::TestCase
         
     | 
| 
      
 1919 
     | 
    
         
            +
              private
         
     | 
| 
      
 1920 
     | 
    
         
            +
             
     | 
| 
      
 1921 
     | 
    
         
            +
              def marshal_fixture_path(file_name)
         
     | 
| 
      
 1922 
     | 
    
         
            +
                File.expand_path(
         
     | 
| 
      
 1923 
     | 
    
         
            +
                  "support/marshal_compatibility_fixtures/#{ActiveRecord::Base.connection.adapter_name}/#{file_name}.dump",
         
     | 
| 
      
 1924 
     | 
    
         
            +
                  ARTest::SQLServer.test_root_sqlserver
         
     | 
| 
      
 1925 
     | 
    
         
            +
                )
         
     | 
| 
      
 1926 
     | 
    
         
            +
              end
         
     | 
| 
       1452 
1927 
     | 
    
         
             
            end
         
     | 
| 
       1453 
1928 
     | 
    
         | 
| 
       1454 
     | 
    
         
            -
            class  
     | 
| 
       1455 
     | 
    
         
            -
              #  
     | 
| 
       1456 
     | 
    
         
            -
              #  
     | 
| 
       1457 
     | 
    
         
            -
               
     | 
| 
      
 1929 
     | 
    
         
            +
            class NestedThroughAssociationsTest < ActiveRecord::TestCase
         
     | 
| 
      
 1930 
     | 
    
         
            +
              # Same as original but replace order with "order(:id)" to ensure that assert_includes_and_joins_equal doesn't raise
         
     | 
| 
      
 1931 
     | 
    
         
            +
              # "A column has been specified more than once in the order by list"
         
     | 
| 
      
 1932 
     | 
    
         
            +
              # Example: original test generate queries like "ORDER BY authors.id, [authors].[id]". We don't support duplicate columns in the order list
         
     | 
| 
      
 1933 
     | 
    
         
            +
              coerce_tests! :test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload_via_joins, :test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload_via_joins
         
     | 
| 
      
 1934 
     | 
    
         
            +
              def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload_via_joins_coerced
         
     | 
| 
      
 1935 
     | 
    
         
            +
                # preload table schemas
         
     | 
| 
      
 1936 
     | 
    
         
            +
                Author.joins(:category_post_comments).first
         
     | 
| 
      
 1937 
     | 
    
         
            +
             
     | 
| 
      
 1938 
     | 
    
         
            +
                assert_includes_and_joins_equal(
         
     | 
| 
      
 1939 
     | 
    
         
            +
                  Author.where("comments.id" => comments(:does_it_hurt).id).order(:id),
         
     | 
| 
      
 1940 
     | 
    
         
            +
                  [authors(:david), authors(:mary)], :category_post_comments
         
     | 
| 
      
 1941 
     | 
    
         
            +
                )
         
     | 
| 
      
 1942 
     | 
    
         
            +
              end
         
     | 
| 
      
 1943 
     | 
    
         
            +
             
     | 
| 
      
 1944 
     | 
    
         
            +
              def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload_via_joins_coerced
         
     | 
| 
      
 1945 
     | 
    
         
            +
                # preload table schemas
         
     | 
| 
      
 1946 
     | 
    
         
            +
                Category.joins(:post_comments).first
         
     | 
| 
      
 1947 
     | 
    
         
            +
             
     | 
| 
      
 1948 
     | 
    
         
            +
                assert_includes_and_joins_equal(
         
     | 
| 
      
 1949 
     | 
    
         
            +
                  Category.where("comments.id" => comments(:more_greetings).id).order(:id),
         
     | 
| 
      
 1950 
     | 
    
         
            +
                  [categories(:general), categories(:technology)], :post_comments
         
     | 
| 
      
 1951 
     | 
    
         
            +
                )
         
     | 
| 
      
 1952 
     | 
    
         
            +
              end
         
     | 
| 
      
 1953 
     | 
    
         
            +
            end
         
     | 
| 
      
 1954 
     | 
    
         
            +
             
     | 
| 
      
 1955 
     | 
    
         
            +
            class BasePreventWritesTest < ActiveRecord::TestCase
         
     | 
| 
      
 1956 
     | 
    
         
            +
              # SQL Server does not have query for release_savepoint
         
     | 
| 
      
 1957 
     | 
    
         
            +
              coerce_tests! %r{an empty transaction does not raise if preventing writes}
         
     | 
| 
      
 1958 
     | 
    
         
            +
              test "an empty transaction does not raise if preventing writes coerced" do
         
     | 
| 
      
 1959 
     | 
    
         
            +
                ActiveRecord::Base.while_preventing_writes do
         
     | 
| 
      
 1960 
     | 
    
         
            +
                  assert_queries(1, ignore_none: true) do
         
     | 
| 
      
 1961 
     | 
    
         
            +
                    Bird.transaction do
         
     | 
| 
      
 1962 
     | 
    
         
            +
                      ActiveRecord::Base.connection.materialize_transactions
         
     | 
| 
      
 1963 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1964 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1965 
     | 
    
         
            +
                end
         
     | 
| 
      
 1966 
     | 
    
         
            +
              end
         
     | 
| 
      
 1967 
     | 
    
         
            +
             
     | 
| 
      
 1968 
     | 
    
         
            +
              class BasePreventWritesLegacyTest < ActiveRecord::TestCase
         
     | 
| 
      
 1969 
     | 
    
         
            +
                # SQL Server does not have query for release_savepoint
         
     | 
| 
      
 1970 
     | 
    
         
            +
                coerce_tests! %r{an empty transaction does not raise if preventing writes}
         
     | 
| 
      
 1971 
     | 
    
         
            +
                test "an empty transaction does not raise if preventing writes coerced" do
         
     | 
| 
      
 1972 
     | 
    
         
            +
                  ActiveRecord::Base.connection_handler.while_preventing_writes do
         
     | 
| 
      
 1973 
     | 
    
         
            +
                    assert_queries(1, ignore_none: true) do
         
     | 
| 
      
 1974 
     | 
    
         
            +
                      Bird.transaction do
         
     | 
| 
      
 1975 
     | 
    
         
            +
                        ActiveRecord::Base.connection.materialize_transactions
         
     | 
| 
      
 1976 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1977 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1978 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1979 
     | 
    
         
            +
                end
         
     | 
| 
      
 1980 
     | 
    
         
            +
              end
         
     | 
| 
      
 1981 
     | 
    
         
            +
            end
         
     | 
| 
      
 1982 
     | 
    
         
            +
             
     | 
| 
      
 1983 
     | 
    
         
            +
            class MigratorTest < ActiveRecord::TestCase
         
     | 
| 
      
 1984 
     | 
    
         
            +
              # Test fails on Windows AppVeyor CI for unknown reason.
         
     | 
| 
      
 1985 
     | 
    
         
            +
              coerce_tests! :test_migrator_db_has_no_schema_migrations_table if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
         
     | 
| 
      
 1986 
     | 
    
         
            +
            end
         
     | 
| 
      
 1987 
     | 
    
         
            +
             
     | 
| 
      
 1988 
     | 
    
         
            +
            class MultiDbMigratorTest < ActiveRecord::TestCase
         
     | 
| 
      
 1989 
     | 
    
         
            +
              # Test fails on Windows AppVeyor CI for unknown reason.
         
     | 
| 
      
 1990 
     | 
    
         
            +
              coerce_tests! :test_migrator_db_has_no_schema_migrations_table if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
         
     | 
| 
       1458 
1991 
     | 
    
         
             
            end
         
     |