djezzzl/database_consistency

View on GitHub
lib/database_consistency/checkers/index_checkers/redundant_unique_index_checker.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

module DatabaseConsistency
  module Checkers
    # This class checks redundant database unique indexes
    class RedundantUniqueIndexChecker < IndexChecker
      Report = ReportBuilder.define(
        DatabaseConsistency::Report,
        :index_name,
        :covered_index_name
      )

      private

      # We skip check when:
      #  - index is not unique
      def preconditions
        index.unique
      end

      # Table of possible statuses
      # | validation | status |
      # | ---------- | ------ |
      # | provided   | ok     |
      # | redundant  | fail   |
      #
      def check
        if covered_by_index
          report_template(:fail, error_slug: :redundant_unique_index)
        else
          report_template(:ok)
        end
      end

      def report_template(status, error_slug: nil)
        Report.new(
          status: status,
          error_slug: error_slug,
          error_message: nil,
          index_name: index.name,
          covered_index_name: covered_by_index&.name,
          **report_attributes
        )
      end

      def covered_by_index
        @covered_by_index ||=
          model.connection.indexes(model.table_name).find do |another_index|
            next if index.name == another_index.name

            another_index.unique && clause_equals?(another_index) && contain_index?(another_index)
          end
      end

      def clause_equals?(another_index)
        another_index.where == index.where
      end

      def contain_index?(another_index)
        another_index_columns = Helper.extract_index_columns(another_index.columns)
        index_columns & another_index_columns == another_index_columns
      end

      def index_columns
        @index_columns ||= Helper.extract_index_columns(index.columns)
      end
    end
  end
end