Skip to content

Instantly share code, notes, and snippets.

@ixti
Created September 13, 2021 22:51
Show Gist options
  • Save ixti/1d3325b9688e87d2b3f7ae1e48d1bda5 to your computer and use it in GitHub Desktop.
Save ixti/1d3325b9688e87d2b3f7ae1e48d1bda5 to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
module ActiveRecord
module Schema
class Context
class Table
class Index
attr_reader :columns, :options
def initialize(columns, **options)
@columns = columns
@options = options
end
end
attr_reader :name
def initialize(name, **, &block)
@name = name
@indices = []
instance_eval(&block)
end
def index(columns, **options)
@indices << Index.new(columns, **options)
end
def redundant_indices
Enumerator.new do |y|
longest_index = nil
@indices.sort_by(&:columns).reverse_each do |index|
next longest_index = index unless longest_index
next longest_index = index unless index.columns == (index.columns & longest_index.columns)
y.yield(index, longest_index)
end
end
end
%i[bigint boolean date datetime json integer string text].each do |dsl|
define_method(dsl) do |*, **|
# do nothing
end
end
end
def initialize(&block)
@tables = []
instance_eval(&block)
end
def create_table(name, **, &block)
@tables << Table.new(name, &block)
end
def print_suggestions
@tables.each do |t|
memo = Hash.new { |h, k| h[k] = [] }
t.redundant_indices.each { |index, covered_by| memo[covered_by] << index }
next if memo.empty?
memo.each do |longer_index, redundant_indices|
puts "# covered by: #{longer_index.options[:name]}"
redundant_indices.each do |index|
puts "remove_index :#{t.name}, %i[#{index.columns.join ' '}]"
end
end
end
end
end
def self.define(**, &block)
Context.new(&block).print_suggestions
end
end
end
require_relative "db/schema"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment