diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c08390700..c11878541 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,7 +13,10 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        ruby: [2.5.9, 2.6.7, 2.7.3, 3.0.1]
+        ruby:
+          - 2.7.5
+          - 3.0.3
+          - 3.1.0
 
     steps:
       - name: Checkout code
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e170796c..21ceec799 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+## v6.1.3.0
+
+[Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.2.1...v6.1.3.0)
+
+#### Fixed
+
+- [#1006](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1006) Fix support for index types
+- [#1041](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1041) Fix hook method that allows custom connection configuration.
+
+#### Changed
+
+- [#1014](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1014) Better handle SQL queries with invalid encoding
+
 ## v6.1.2.1
 
 [Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.2.0...v6.1.2.1)
diff --git a/Gemfile b/Gemfile
index e81c9033f..c8de851a1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -7,9 +7,12 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
 gemspec
 
 gem "bcrypt"
-gem "pg",      ">= 0.18.0"
+
+gem "pg", "~> 1.3"
+
 gem "sqlite3", "~> 1.4"
 gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+gem "minitest", ">= 5.15.0", "< 5.16"
 
 if ENV["RAILS_SOURCE"]
   gemspec path: ENV["RAILS_SOURCE"]
diff --git a/README.md b/README.md
index 88263931c..4db33262a 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,8 @@ The SQL Server adapter for ActiveRecord using SQL Server 2012 or higher.
 Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 6.x version of the adapter is only for the latest 6.x version of Rails. If you need the adapter for SQL Server 2008 or 2005, you are still in the right spot. Just install the latest 3.2.x to 4.1.x version of the adapter that matches your Rails version. We also have stable branches for each major/minor release of ActiveRecord.
 
 | Adapter Version | Rails Version | Support                                                                                     |
-| --------------- | ------------- | ------------------------------------------------------------------------------------------- |
-| `6.1.2.1`       | `6.1.x`       | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main)       |
+|-----------------| ------------- |---------------------------------------------------------------------------------------------|
+| `6.1.3.0`       | `6.1.x`       | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-1-stable) |
 | `6.0.2`         | `6.0.x`       | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable) |
 | `5.2.1`         | `5.2.x`       | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-2-stable) |
 | `5.1.6`         | `5.1.x`       | [ended](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-1-stable)  |
@@ -84,7 +84,7 @@ end
 
 #### Configure Connection
 
-We currently conform to an unpublished and non-standard AbstractAdapter interface to configure connections made to the database. To do so, just override the `configure_connection` method in an initializer like so. In this case below we are setting the `TEXTSIZE` to 64 megabytes.
+We currently conform to an unpublished and non-standard AbstractAdapter interface to configure connections made to the database. To do so, just implement the `configure_connection` method in an initializer like so. In this case below we are setting the `TEXTSIZE` to 64 megabytes.
 
 ```ruby
 module ActiveRecord
diff --git a/VERSION b/VERSION
index 93165af1f..8d68fd8db 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.1.2.1
+6.1.3.0
diff --git a/appveyor.yml b/appveyor.yml
index 7b4d943de..da7123a06 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,10 +5,10 @@ build: off
 matrix:
   fast_finish: true
   allow_failures:
-    - ruby_version: "25"
-    - ruby_version: "26"
     - ruby_version: "27"
     - ruby_version: "27-x64"
+    - ruby_version: "30"
+    - ruby_version: "30-x64"
 services:
   - mssql2014
 
@@ -38,9 +38,7 @@ environment:
   CI_AZURE_PASS:
     secure: cSQp8sk4urJYvq0utpsK+r7J+snJ2wpcdp8RdXJfB+w=
   matrix:
-    - ruby_version: "25-x64"
-    - ruby_version: "25"
-    - ruby_version: "26-x64"
-    - ruby_version: "26"
     - ruby_version: "27-x64"
     - ruby_version: "27"
+    - ruby_version: "30-x64"
+    - ruby_version: "30"
diff --git a/lib/active_record/connection_adapters/sqlserver/database_statements.rb b/lib/active_record/connection_adapters/sqlserver/database_statements.rb
index fbab539be..ea5fea3eb 100644
--- a/lib/active_record/connection_adapters/sqlserver/database_statements.rb
+++ b/lib/active_record/connection_adapters/sqlserver/database_statements.rb
@@ -9,6 +9,8 @@ module DatabaseStatements
 
         def write_query?(sql) # :nodoc:
           !READ_QUERY.match?(sql)
+        rescue ArgumentError # Invalid encoding
+          !READ_QUERY.match?(sql.b)
         end
 
         def execute(sql, name = nil)
diff --git a/lib/active_record/connection_adapters/sqlserver/schema_creation.rb b/lib/active_record/connection_adapters/sqlserver/schema_creation.rb
index 0b70b8d50..95710ae8e 100644
--- a/lib/active_record/connection_adapters/sqlserver/schema_creation.rb
+++ b/lib/active_record/connection_adapters/sqlserver/schema_creation.rb
@@ -34,17 +34,19 @@ def visit_TableDefinition(o)
         end
 
         def visit_CreateIndexDefinition(o)
-          if_not_exists = o.if_not_exists
-
-          o.if_not_exists = false
-
-          sql = super
+          index = o.index
 
-          if if_not_exists
-            sql = "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '#{o.index.name}') #{sql}"
-          end
+          sql = []
+          sql << "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '#{o.index.name}')" if o.if_not_exists
+          sql << "CREATE"
+          sql << "UNIQUE" if index.unique
+          sql << index.type.upcase if index.type
+          sql << "INDEX"
+          sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
+          sql << "(#{quoted_columns(index)})"
+          sql << "WHERE #{index.where}" if index.where
 
-          sql
+          sql.join(" ")
         end
 
         def add_column_options!(sql, options)
diff --git a/lib/active_record/connection_adapters/sqlserver_adapter.rb b/lib/active_record/connection_adapters/sqlserver_adapter.rb
index 4ce55cb96..0ce12fea8 100644
--- a/lib/active_record/connection_adapters/sqlserver_adapter.rb
+++ b/lib/active_record/connection_adapters/sqlserver_adapter.rb
@@ -140,7 +140,7 @@ def config_encoding(config)
       def initialize(connection, logger, _connection_options, config)
         super(connection, logger, config)
         @connection_options = config
-        configure_connection
+        perform_connection_configuration
       end
 
       # === Abstract Adapter ========================================== #
@@ -301,14 +301,6 @@ def reset!
         do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
       end
 
-      def configure_connection
-        @spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
-        @version_year = version_year
-
-        initialize_dateformatter
-        use_database
-      end
-
       # === Abstract Adapter (Misc Support) =========================== #
 
       def tables_with_referential_integrity
@@ -530,7 +522,20 @@ def sqlserver_version
 
       def connect
         @connection = self.class.new_client(@connection_options)
-        configure_connection
+        perform_connection_configuration
+      end
+
+      def perform_connection_configuration
+        configure_connection_defaults
+        configure_connection if self.respond_to?(:configure_connection)
+      end
+
+      def configure_connection_defaults
+        @spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
+        @version_year = version_year
+
+        initialize_dateformatter
+        use_database
       end
     end
   end
diff --git a/test/cases/active_schema_test_sqlserver.rb b/test/cases/active_schema_test_sqlserver.rb
new file mode 100644
index 000000000..6d38f5820
--- /dev/null
+++ b/test/cases/active_schema_test_sqlserver.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require "cases/helper_sqlserver"
+
+class ActiveSchemaTestSQLServer < ActiveRecord::TestCase
+  before do
+    connection.create_table :schema_test_table, force: true, id: false do |t|
+      t.column :foo, :string, limit: 100
+      t.column :state, :string
+    end
+  end
+
+  after do
+    connection.drop_table :schema_test_table rescue nil
+  end
+
+  it 'default index' do
+    assert_sql('CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
+      connection.add_index :schema_test_table, "foo"
+    end
+  end
+
+  it 'unique index' do
+    assert_sql('CREATE UNIQUE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
+      connection.add_index :schema_test_table, "foo", unique: true
+    end
+  end
+
+  it 'where condition on index' do
+    assert_sql("CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo]) WHERE state = 'active'") do
+      connection.add_index :schema_test_table, "foo", where: "state = 'active'"
+    end
+  end
+
+  it 'if index does not exist' do
+    assert_sql("IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = 'index_schema_test_table_on_foo') " \
+               "CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])") do
+      connection.add_index :schema_test_table, "foo", if_not_exists: true
+    end
+  end
+
+  describe "index types" do
+    it 'clustered index' do
+      assert_sql('CREATE CLUSTERED INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
+        connection.add_index :schema_test_table, "foo", type: :clustered
+      end
+    end
+
+    it 'nonclustered index' do
+      assert_sql('CREATE NONCLUSTERED INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
+        connection.add_index :schema_test_table, "foo", type: :nonclustered
+      end
+    end
+  end
+end
diff --git a/test/cases/coerced_tests.rb b/test/cases/coerced_tests.rb
index 4d603513e..44d273810 100644
--- a/test/cases/coerced_tests.rb
+++ b/test/cases/coerced_tests.rb
@@ -92,6 +92,18 @@ def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called
       Subscriber.send(:load_schema!)
       original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
     end
+
+    coerce_tests! :test_doesnt_error_when_a_select_query_has_encoding_errors
+    def test_doesnt_error_when_a_select_query_has_encoding_errors_coerced
+      ActiveRecord::Base.while_preventing_writes do
+        # TinyTDS fail on encoding errors.
+        # But at least we can assert it fails in the client and not before when trying to
+        # match the query.
+        assert_raises ActiveRecord::StatementInvalid do
+          @connection.select_all("SELECT '\xC8'")
+        end
+      end
+    end
   end
 end
 
@@ -1195,7 +1207,7 @@ def test_reorder_with_first_coerced
     sql_log = capture_sql do
       message = <<~MSG.squish
         `.reorder(nil)` with `.first` / `.first!` no longer
-        takes non-deterministic result in Rails 6.2.
+        takes non-deterministic result in Rails 7.0.
         To continue taking non-deterministic result, use `.take` / `.take!` instead.
       MSG
       assert_deprecated(message) do
@@ -1402,7 +1414,8 @@ class YamlSerializationTest < ActiveRecord::TestCase
   coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
   def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
     author = Author.select("authors.*, 5 as posts_count").first
-    dumped = YAML.load(YAML.dump(author))
+    dumped_author = YAML.dump(author)
+    dumped = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(dumped_author) : YAML.load(dumped_author)
     assert_equal 5, author.posts_count
     assert_equal 5, dumped.posts_count
   end
@@ -1893,17 +1906,22 @@ def test_annotate_wraps_content_in_an_inline_comment_coerced
   def test_annotate_is_sanitized_coerced
     quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
 
-    assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
+    assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/}i) do
       posts = Post.select(:id).annotate("*/foo/*")
       assert posts.first
     end
 
-    assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
+    assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \*\* //foo// \*\* \*/}i) do
       posts = Post.select(:id).annotate("**//foo//**")
       assert posts.first
     end
 
-    assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/ /\* bar \*/}i) do
+    assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* \* //foo// \* \* \*/}i) do
+      posts = Post.select(:id).annotate("* *//foo//* *")
+      assert posts.first
+    end
+
+    assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/ /\* \* /bar \*/}i) do
       posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
       assert posts.first
     end
diff --git a/test/cases/rake_test_sqlserver.rb b/test/cases/rake_test_sqlserver.rb
index 1195713d2..0cecf65e9 100644
--- a/test/cases/rake_test_sqlserver.rb
+++ b/test/cases/rake_test_sqlserver.rb
@@ -176,7 +176,8 @@ class SQLServerRakeSchemaCacheDumpLoadTest < SQLServerRakeTest
   it "dumps schema cache with SQL Server metadata" do
     quietly { db_tasks.dump_schema_cache connection, filename }
 
-    schema_cache = YAML.load(File.read(filename))
+    filedata = File.read(filename)
+    schema_cache = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(filedata) : YAML.load(filedata)
 
     col_id, col_name = connection.schema_cache.columns("users")
 
