diff --git a/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
index f367292f4b0a4960fe35f08021e1ddf04f91f289..0bc1343acca129ed6edf854838186000dd24efe5 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb
@@ -32,7 +32,7 @@ def add_concurrent_partitioned_index(table_name, column_names, options = {})
             return
           end
 
-          partitioned_table.postgres_partitions.each do |partition|
+          partitioned_table.postgres_partitions.order(:name).each do |partition|
             partition_index_name = generated_index_name(partition.identifier, options[:name])
             partition_options = options.merge(name: partition_index_name)
 
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 1afd5bdb2cadd1b6f513a8275918852fc157fbfb..38ade20de2868721d8e6d00892726b23b8ae0fbf 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -3,7 +3,7 @@
 require 'spec_helper'
 
 RSpec.describe 'factories' do
-  include DatabaseHelpers
+  include Database::DatabaseHelpers
 
   shared_examples 'factory' do |factory|
     describe "#{factory.name} factory" do
diff --git a/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb b/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb
index 563999416628f422bcb106fe8cc0f6b7f4bdb539..ec89f2ed61c775e9fc15d21c0d4fb7437260296d 100644
--- a/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/partition_creator_spec.rb
@@ -3,7 +3,7 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::Database::Partitioning::PartitionCreator do
-  include PartitioningHelpers
+  include Database::PartitioningHelpers
   include ExclusiveLeaseHelpers
 
   describe '.register' do
diff --git a/spec/lib/gitlab/database/partitioning/replace_table_spec.rb b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
index d47666eeffd205ea9b8d9afe14a0c1a6a9559fdd..8e27797208c7a107add9aa5e115c4db2ddee9a09 100644
--- a/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
@@ -3,7 +3,7 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::Database::Partitioning::ReplaceTable, '#perform' do
-  include TableSchemaHelpers
+  include Database::TableSchemaHelpers
 
   subject(:replace_table) { described_class.new(original_table, replacement_table, archived_table, 'id').perform }
 
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb
index 7d88c17c9b373d3f40f0c5fc5e1134c20d4d7245..93dbd9d7c30021d96893f9cfb604c60f91f29df6 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb
@@ -3,7 +3,7 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::ForeignKeyHelpers do
-  include TriggerHelpers
+  include Database::TriggerHelpers
 
   let(:model) do
     ActiveRecord::Migration.new.extend(described_class)
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
index 7f61ff759fc8137efeaf6009727716f373c0ca1d..603f3dc41af52b89efb3c447cf38299bfcd4a8d4 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb
@@ -3,7 +3,7 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::IndexHelpers do
-  include TableSchemaHelpers
+  include Database::TableSchemaHelpers
 
   let(:migration) do
     ActiveRecord::Migration.new.extend(described_class)
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
index f10ff704c178b9e72a542257550a10e9b225acd5..5fdb7dd9a85f47c62344c64a104a2ae7c1576420 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
@@ -3,9 +3,9 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers do
-  include PartitioningHelpers
-  include TriggerHelpers
-  include TableSchemaHelpers
+  include Database::PartitioningHelpers
+  include Database::TriggerHelpers
+  include Database::TableSchemaHelpers
 
   let(:migration) do
     ActiveRecord::Migration.new.extend(described_class)
diff --git a/spec/lib/gitlab/database/reindexing/index_selection_spec.rb b/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
index a5e2f368f406c63599d3d096d5d67c8361a1f85e..4466679a099ec76a912c9773de5e8e3ae292a586 100644
--- a/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
@@ -3,7 +3,7 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::Database::Reindexing::IndexSelection do
-  include DatabaseHelpers
+  include Database::DatabaseHelpers
 
   subject { described_class.new(Gitlab::Database::PostgresIndex.all).to_a }
 
diff --git a/spec/support/helpers/database/database_helpers.rb b/spec/support/helpers/database/database_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b8d7ea3662f98d877af6ed07056d37e4db709e43
--- /dev/null
+++ b/spec/support/helpers/database/database_helpers.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Database
+  module DatabaseHelpers
+    # In order to directly work with views using factories,
+    # we can swapout the view for a table of identical structure.
+    def swapout_view_for_table(view)
+      ActiveRecord::Base.connection.execute(<<~SQL)
+        CREATE TABLE #{view}_copy (LIKE #{view});
+        DROP VIEW #{view};
+        ALTER TABLE #{view}_copy RENAME TO #{view};
+      SQL
+    end
+  end
+end
diff --git a/spec/support/helpers/database/partitioning_helpers.rb b/spec/support/helpers/database/partitioning_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..80b31fe06032595e3618aa10a2a4419a6a2564e7
--- /dev/null
+++ b/spec/support/helpers/database/partitioning_helpers.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+module Database
+  module PartitioningHelpers
+    def expect_table_partitioned_by(table, columns, part_type: :range)
+      columns_with_part_type = columns.map { |c| [part_type.to_s, c] }
+      actual_columns = find_partitioned_columns(table)
+
+      expect(columns_with_part_type).to match_array(actual_columns)
+    end
+
+    def expect_range_partition_of(partition_name, table_name, min_value, max_value)
+      definition = find_partition_definition(partition_name, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+
+      expect(definition).not_to be_nil
+      expect(definition['base_table']).to eq(table_name.to_s)
+      expect(definition['condition']).to eq("FOR VALUES FROM (#{min_value}) TO (#{max_value})")
+    end
+
+    def expect_total_partitions(table_name, count, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+      partitions = find_partitions(table_name, schema: schema)
+
+      expect(partitions.size).to eq(count)
+    end
+
+    def expect_range_partitions_for(table_name, partitions)
+      partitions.each do |suffix, (min_value, max_value)|
+        partition_name = "#{table_name}_#{suffix}"
+        expect_range_partition_of(partition_name, table_name, min_value, max_value)
+      end
+
+      expect_total_partitions(table_name, partitions.size, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+    end
+
+    def expect_hash_partition_of(partition_name, table_name, modulus, remainder)
+      definition = find_partition_definition(partition_name, schema: Gitlab::Database::STATIC_PARTITIONS_SCHEMA)
+
+      expect(definition).not_to be_nil
+      expect(definition['base_table']).to eq(table_name.to_s)
+      expect(definition['condition']).to eq("FOR VALUES WITH (modulus #{modulus}, remainder #{remainder})")
+    end
+
+    private
+
+    def find_partitioned_columns(table)
+      connection.select_rows(<<~SQL)
+        select
+          case partstrat
+          when 'l' then 'list'
+          when 'r' then 'range'
+          when 'h' then 'hash'
+          end as partstrat,
+          cols.column_name
+        from (
+          select partrelid, partstrat, unnest(partattrs) as col_pos
+          from pg_partitioned_table
+        ) pg_part
+        inner join pg_class
+        on pg_part.partrelid = pg_class.oid
+        inner join information_schema.columns cols
+        on cols.table_name = pg_class.relname
+        and cols.ordinal_position = pg_part.col_pos
+        where pg_class.relname = '#{table}';
+      SQL
+    end
+
+    def find_partition_definition(partition, schema: )
+      connection.select_one(<<~SQL)
+        select
+          parent_class.relname as base_table,
+          pg_get_expr(pg_class.relpartbound, inhrelid) as condition
+        from pg_class
+        inner join pg_inherits i on pg_class.oid = inhrelid
+        inner join pg_class parent_class on parent_class.oid = inhparent
+        inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
+        where pg_namespace.nspname = '#{schema}'
+          and pg_class.relname = '#{partition}'
+          and pg_class.relispartition
+      SQL
+    end
+
+    def find_partitions(partition, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
+      connection.select_rows(<<~SQL)
+        select
+          pg_class.relname
+        from pg_class
+        inner join pg_inherits i on pg_class.oid = inhrelid
+        inner join pg_class parent_class on parent_class.oid = inhparent
+        inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
+        where pg_namespace.nspname = '#{schema}'
+          and parent_class.relname = '#{partition}'
+          and pg_class.relispartition
+      SQL
+    end
+  end
+end
diff --git a/spec/support/helpers/database/table_schema_helpers.rb b/spec/support/helpers/database/table_schema_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..854d2c94df2ba74a6f786427108dffbc4ea9adba
--- /dev/null
+++ b/spec/support/helpers/database/table_schema_helpers.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+module Database
+  module TableSchemaHelpers
+    def connection
+      ActiveRecord::Base.connection
+    end
+
+    def expect_table_to_be_replaced(original_table:, replacement_table:, archived_table:)
+      original_oid = table_oid(original_table)
+      replacement_oid = table_oid(replacement_table)
+
+      yield
+
+      expect(table_oid(original_table)).to eq(replacement_oid)
+      expect(table_oid(archived_table)).to eq(original_oid)
+      expect(table_oid(replacement_table)).to be_nil
+    end
+
+    def expect_index_to_exist(name, schema: nil)
+      expect(index_exists_by_name(name, schema: schema)).to eq(true)
+    end
+
+    def expect_index_not_to_exist(name, schema: nil)
+      expect(index_exists_by_name(name, schema: schema)).to be_nil
+    end
+
+    def expect_primary_keys_after_tables(tables, schema: nil)
+      tables.each do |table|
+        primary_key = primary_key_constraint_name(table, schema: schema)
+
+        expect(primary_key).to eq("#{table}_pkey")
+      end
+    end
+
+    def table_oid(name)
+      connection.select_value(<<~SQL)
+        SELECT oid
+        FROM pg_catalog.pg_class
+        WHERE relname = '#{name}'
+      SQL
+    end
+
+    def table_type(name)
+      connection.select_value(<<~SQL)
+        SELECT
+          CASE class.relkind
+          WHEN 'r' THEN 'normal'
+          WHEN 'p' THEN 'partitioned'
+          ELSE 'other'
+          END as table_type
+        FROM pg_catalog.pg_class class
+        WHERE class.relname = '#{name}'
+      SQL
+    end
+
+    def sequence_owned_by(table_name, column_name)
+      connection.select_value(<<~SQL)
+        SELECT
+          sequence.relname as name
+        FROM pg_catalog.pg_class as sequence
+        INNER JOIN pg_catalog.pg_depend depend
+          ON depend.objid = sequence.oid
+        INNER JOIN pg_catalog.pg_class class
+          ON class.oid = depend.refobjid
+        INNER JOIN pg_catalog.pg_attribute attribute
+          ON attribute.attnum = depend.refobjsubid
+          AND attribute.attrelid = depend.refobjid
+        WHERE class.relname = '#{table_name}'
+          AND attribute.attname = '#{column_name}'
+      SQL
+    end
+
+    def default_expression_for(table_name, column_name)
+      connection.select_value(<<~SQL)
+        SELECT
+          pg_get_expr(attrdef.adbin, attrdef.adrelid) AS default_value
+        FROM pg_catalog.pg_attribute attribute
+        INNER JOIN pg_catalog.pg_attrdef attrdef
+          ON attribute.attrelid = attrdef.adrelid
+          AND attribute.attnum = attrdef.adnum
+        WHERE attribute.attrelid = '#{table_name}'::regclass
+          AND attribute.attname = '#{column_name}'
+      SQL
+    end
+
+    def primary_key_constraint_name(table_name, schema: nil)
+      table_name = schema ? "#{schema}.#{table_name}" : table_name
+
+      connection.select_value(<<~SQL)
+        SELECT
+          conname AS constraint_name
+        FROM pg_catalog.pg_constraint
+        WHERE pg_constraint.conrelid = '#{table_name}'::regclass
+          AND pg_constraint.contype = 'p'
+      SQL
+    end
+
+    def index_exists_by_name(index, schema: nil)
+      schema = schema ? "'#{schema}'" : 'current_schema'
+
+      connection.select_value(<<~SQL)
+        SELECT true
+        FROM pg_catalog.pg_index i
+        INNER JOIN pg_catalog.pg_class c
+          ON c.oid = i.indexrelid
+        INNER JOIN pg_catalog.pg_namespace n
+          ON c.relnamespace = n.oid
+        WHERE c.relname = '#{index}'
+          AND n.nspname = #{schema}
+      SQL
+    end
+  end
+end
diff --git a/spec/support/helpers/database/trigger_helpers.rb b/spec/support/helpers/database/trigger_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9ec03e684138b663ae1b255ef5c4b9703cb98ddb
--- /dev/null
+++ b/spec/support/helpers/database/trigger_helpers.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Database
+  module TriggerHelpers
+    def expect_function_to_exist(name)
+      expect(find_function_def(name)).not_to be_nil
+    end
+
+    def expect_function_not_to_exist(name)
+      expect(find_function_def(name)).to be_nil
+    end
+
+    def expect_function_to_contain(name, *statements)
+      return_stmt, *body_stmts = parsed_function_statements(name).reverse
+
+      expect(return_stmt).to eq('return old')
+      expect(body_stmts).to contain_exactly(*statements)
+    end
+
+    def expect_trigger_not_to_exist(table_name, name)
+      expect(find_trigger_def(table_name, name)).to be_nil
+    end
+
+    def expect_valid_function_trigger(table_name, name, fn_name, fires_on)
+      events, timing, definition = cleaned_trigger_def(table_name, name)
+
+      events = events&.split(',')
+      expected_timing, expected_events = fires_on.first
+      expect(timing).to eq(expected_timing.to_s)
+      expect(events).to match_array(Array.wrap(expected_events))
+
+      expect(definition).to match(%r{execute (?:procedure|function) #{fn_name}()})
+    end
+
+    private
+
+    def parsed_function_statements(name)
+      cleaned_definition = find_function_def(name)['body'].downcase.gsub(/\s+/, ' ')
+      statements = cleaned_definition.sub(/\A\s*begin\s*(.*)\s*end\s*\Z/, "\\1")
+      statements.split(';').map! { |stmt| stmt.strip.presence }.compact!
+    end
+
+    def find_function_def(name)
+      connection.select_one(<<~SQL)
+        SELECT prosrc AS body
+        FROM pg_proc
+        WHERE proname = '#{name}'
+      SQL
+    end
+
+    def cleaned_trigger_def(table_name, name)
+      find_trigger_def(table_name, name).values_at('event', 'action_timing', 'action_statement').map!(&:downcase)
+    end
+
+    def find_trigger_def(table_name, name)
+      connection.select_one(<<~SQL)
+        SELECT
+          string_agg(event_manipulation, ',') AS event,
+          action_timing,
+          action_statement
+        FROM information_schema.triggers
+        WHERE event_object_table = '#{table_name}'
+        AND trigger_name = '#{name}'
+        GROUP BY 2, 3
+      SQL
+    end
+  end
+end
diff --git a/spec/support/helpers/database_helpers.rb b/spec/support/helpers/database_helpers.rb
deleted file mode 100644
index e9f0a74a8d1060f4b253c69691d6c17ec196c071..0000000000000000000000000000000000000000
--- a/spec/support/helpers/database_helpers.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module DatabaseHelpers
-  # In order to directly work with views using factories,
-  # we can swapout the view for a table of identical structure.
-  def swapout_view_for_table(view)
-    ActiveRecord::Base.connection.execute(<<~SQL)
-      CREATE TABLE #{view}_copy (LIKE #{view});
-      DROP VIEW #{view};
-      ALTER TABLE #{view}_copy RENAME TO #{view};
-    SQL
-  end
-end
diff --git a/spec/support/helpers/partitioning_helpers.rb b/spec/support/helpers/partitioning_helpers.rb
deleted file mode 100644
index 8981fea04d53795aa34c417938cd1badf5ed7c45..0000000000000000000000000000000000000000
--- a/spec/support/helpers/partitioning_helpers.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-module PartitioningHelpers
-  def expect_table_partitioned_by(table, columns, part_type: :range)
-    columns_with_part_type = columns.map { |c| [part_type.to_s, c] }
-    actual_columns = find_partitioned_columns(table)
-
-    expect(columns_with_part_type).to match_array(actual_columns)
-  end
-
-  def expect_range_partition_of(partition_name, table_name, min_value, max_value)
-    definition = find_partition_definition(partition_name, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
-
-    expect(definition).not_to be_nil
-    expect(definition['base_table']).to eq(table_name.to_s)
-    expect(definition['condition']).to eq("FOR VALUES FROM (#{min_value}) TO (#{max_value})")
-  end
-
-  def expect_total_partitions(table_name, count, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
-    partitions = find_partitions(table_name, schema: schema)
-
-    expect(partitions.size).to eq(count)
-  end
-
-  def expect_range_partitions_for(table_name, partitions)
-    partitions.each do |suffix, (min_value, max_value)|
-      partition_name = "#{table_name}_#{suffix}"
-      expect_range_partition_of(partition_name, table_name, min_value, max_value)
-    end
-
-    expect_total_partitions(table_name, partitions.size, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
-  end
-
-  def expect_hash_partition_of(partition_name, table_name, modulus, remainder)
-    definition = find_partition_definition(partition_name, schema: Gitlab::Database::STATIC_PARTITIONS_SCHEMA)
-
-    expect(definition).not_to be_nil
-    expect(definition['base_table']).to eq(table_name.to_s)
-    expect(definition['condition']).to eq("FOR VALUES WITH (modulus #{modulus}, remainder #{remainder})")
-  end
-
-  private
-
-  def find_partitioned_columns(table)
-    connection.select_rows(<<~SQL)
-      select
-        case partstrat
-        when 'l' then 'list'
-        when 'r' then 'range'
-        when 'h' then 'hash'
-        end as partstrat,
-        cols.column_name
-      from (
-        select partrelid, partstrat, unnest(partattrs) as col_pos
-        from pg_partitioned_table
-      ) pg_part
-      inner join pg_class
-      on pg_part.partrelid = pg_class.oid
-      inner join information_schema.columns cols
-      on cols.table_name = pg_class.relname
-      and cols.ordinal_position = pg_part.col_pos
-      where pg_class.relname = '#{table}';
-    SQL
-  end
-
-  def find_partition_definition(partition, schema: )
-    connection.select_one(<<~SQL)
-      select
-        parent_class.relname as base_table,
-        pg_get_expr(pg_class.relpartbound, inhrelid) as condition
-      from pg_class
-      inner join pg_inherits i on pg_class.oid = inhrelid
-      inner join pg_class parent_class on parent_class.oid = inhparent
-      inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
-      where pg_namespace.nspname = '#{schema}'
-        and pg_class.relname = '#{partition}'
-        and pg_class.relispartition
-    SQL
-  end
-
-  def find_partitions(partition, schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)
-    connection.select_rows(<<~SQL)
-      select
-        pg_class.relname
-      from pg_class
-      inner join pg_inherits i on pg_class.oid = inhrelid
-      inner join pg_class parent_class on parent_class.oid = inhparent
-      inner join pg_namespace ON pg_namespace.oid = pg_class.relnamespace
-      where pg_namespace.nspname = '#{schema}'
-        and parent_class.relname = '#{partition}'
-        and pg_class.relispartition
-    SQL
-  end
-end
diff --git a/spec/support/helpers/table_schema_helpers.rb b/spec/support/helpers/table_schema_helpers.rb
deleted file mode 100644
index 287942111905548cef5cee5db26f8470844d8b48..0000000000000000000000000000000000000000
--- a/spec/support/helpers/table_schema_helpers.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-# frozen_string_literal: true
-
-module TableSchemaHelpers
-  def connection
-    ActiveRecord::Base.connection
-  end
-
-  def expect_table_to_be_replaced(original_table:, replacement_table:, archived_table:)
-    original_oid = table_oid(original_table)
-    replacement_oid = table_oid(replacement_table)
-
-    yield
-
-    expect(table_oid(original_table)).to eq(replacement_oid)
-    expect(table_oid(archived_table)).to eq(original_oid)
-    expect(table_oid(replacement_table)).to be_nil
-  end
-
-  def expect_index_to_exist(name, schema: nil)
-    expect(index_exists_by_name(name, schema: schema)).to eq(true)
-  end
-
-  def expect_index_not_to_exist(name, schema: nil)
-    expect(index_exists_by_name(name, schema: schema)).to be_nil
-  end
-
-  def expect_primary_keys_after_tables(tables, schema: nil)
-    tables.each do |table|
-      primary_key = primary_key_constraint_name(table, schema: schema)
-
-      expect(primary_key).to eq("#{table}_pkey")
-    end
-  end
-
-  def table_oid(name)
-    connection.select_value(<<~SQL)
-      SELECT oid
-      FROM pg_catalog.pg_class
-      WHERE relname = '#{name}'
-    SQL
-  end
-
-  def table_type(name)
-    connection.select_value(<<~SQL)
-      SELECT
-        CASE class.relkind
-        WHEN 'r' THEN 'normal'
-        WHEN 'p' THEN 'partitioned'
-        ELSE 'other'
-        END as table_type
-      FROM pg_catalog.pg_class class
-      WHERE class.relname = '#{name}'
-    SQL
-  end
-
-  def sequence_owned_by(table_name, column_name)
-    connection.select_value(<<~SQL)
-      SELECT
-        sequence.relname as name
-      FROM pg_catalog.pg_class as sequence
-      INNER JOIN pg_catalog.pg_depend depend
-        ON depend.objid = sequence.oid
-      INNER JOIN pg_catalog.pg_class class
-        ON class.oid = depend.refobjid
-      INNER JOIN pg_catalog.pg_attribute attribute
-        ON attribute.attnum = depend.refobjsubid
-        AND attribute.attrelid = depend.refobjid
-      WHERE class.relname = '#{table_name}'
-        AND attribute.attname = '#{column_name}'
-    SQL
-  end
-
-  def default_expression_for(table_name, column_name)
-    connection.select_value(<<~SQL)
-      SELECT
-        pg_get_expr(attrdef.adbin, attrdef.adrelid) AS default_value
-      FROM pg_catalog.pg_attribute attribute
-      INNER JOIN pg_catalog.pg_attrdef attrdef
-        ON attribute.attrelid = attrdef.adrelid
-        AND attribute.attnum = attrdef.adnum
-      WHERE attribute.attrelid = '#{table_name}'::regclass
-        AND attribute.attname = '#{column_name}'
-    SQL
-  end
-
-  def primary_key_constraint_name(table_name, schema: nil)
-    table_name = schema ? "#{schema}.#{table_name}" : table_name
-
-    connection.select_value(<<~SQL)
-      SELECT
-        conname AS constraint_name
-      FROM pg_catalog.pg_constraint
-      WHERE pg_constraint.conrelid = '#{table_name}'::regclass
-        AND pg_constraint.contype = 'p'
-    SQL
-  end
-
-  def index_exists_by_name(index, schema: nil)
-    schema = schema ? "'#{schema}'" : 'current_schema'
-
-    connection.select_value(<<~SQL)
-      SELECT true
-      FROM pg_catalog.pg_index i
-      INNER JOIN pg_catalog.pg_class c
-        ON c.oid = i.indexrelid
-      INNER JOIN pg_catalog.pg_namespace n
-        ON c.relnamespace = n.oid
-      WHERE c.relname = '#{index}'
-        AND n.nspname = #{schema}
-    SQL
-  end
-end
diff --git a/spec/support/helpers/trigger_helpers.rb b/spec/support/helpers/trigger_helpers.rb
deleted file mode 100644
index dd6d8ff5bb56fe70424ded46c143640a440e1a41..0000000000000000000000000000000000000000
--- a/spec/support/helpers/trigger_helpers.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-module TriggerHelpers
-  def expect_function_to_exist(name)
-    expect(find_function_def(name)).not_to be_nil
-  end
-
-  def expect_function_not_to_exist(name)
-    expect(find_function_def(name)).to be_nil
-  end
-
-  def expect_function_to_contain(name, *statements)
-    return_stmt, *body_stmts = parsed_function_statements(name).reverse
-
-    expect(return_stmt).to eq('return old')
-    expect(body_stmts).to contain_exactly(*statements)
-  end
-
-  def expect_trigger_not_to_exist(table_name, name)
-    expect(find_trigger_def(table_name, name)).to be_nil
-  end
-
-  def expect_valid_function_trigger(table_name, name, fn_name, fires_on)
-    events, timing, definition = cleaned_trigger_def(table_name, name)
-
-    events = events&.split(',')
-    expected_timing, expected_events = fires_on.first
-    expect(timing).to eq(expected_timing.to_s)
-    expect(events).to match_array(Array.wrap(expected_events))
-
-    expect(definition).to match(%r{execute (?:procedure|function) #{fn_name}()})
-  end
-
-  private
-
-  def parsed_function_statements(name)
-    cleaned_definition = find_function_def(name)['body'].downcase.gsub(/\s+/, ' ')
-    statements = cleaned_definition.sub(/\A\s*begin\s*(.*)\s*end\s*\Z/, "\\1")
-    statements.split(';').map! { |stmt| stmt.strip.presence }.compact!
-  end
-
-  def find_function_def(name)
-    connection.select_one(<<~SQL)
-      SELECT prosrc AS body
-      FROM pg_proc
-      WHERE proname = '#{name}'
-    SQL
-  end
-
-  def cleaned_trigger_def(table_name, name)
-    find_trigger_def(table_name, name).values_at('event', 'action_timing', 'action_statement').map!(&:downcase)
-  end
-
-  def find_trigger_def(table_name, name)
-    connection.select_one(<<~SQL)
-      SELECT
-        string_agg(event_manipulation, ',') AS event,
-        action_timing,
-        action_statement
-      FROM information_schema.triggers
-      WHERE event_object_table = '#{table_name}'
-      AND trigger_name = '#{name}'
-      GROUP BY 2, 3
-    SQL
-  end
-end