class FullTableScanMatchers::DBAdapters::MySql::ExplainResult

Attributes

backtrace[RW]
sql_statement[RW]
structs[RW]
tables[RW]

Public Class Methods

new(sql_statement, backtrace: nil, tables: nil) click to toggle source
# File lib/full_table_scan_matchers/db_adapters/mysql/explain_result.rb, line 9
def initialize(sql_statement, backtrace: nil, tables: nil)
  @sql_statement = sql_statement
  @backtrace     = backtrace
  @tables        = tables
end

Public Instance Methods

full_table_scan?() click to toggle source
# File lib/full_table_scan_matchers/db_adapters/mysql/explain_result.rb, line 15
def full_table_scan?
  offending_structs.any?
end
to_s() click to toggle source
# File lib/full_table_scan_matchers/db_adapters/mysql/explain_result.rb, line 23
def to_s
  [
    "SQL:  #{sql_statement}",
    structs.map do |struct|
      (offending_structs.include?(struct) ? "FAIL: " : "INFO: ") +
      struct.to_h.map { |k, v| "#{k}: #{v}" }.join(", ")
    end,
    (backtrace.present? ? "BACKTRACE: #{backtrace}" : nil)
  ].flatten.compact.join "\n"
end

Private Instance Methods

as_hashes() click to toggle source
# File lib/full_table_scan_matchers/db_adapters/mysql/explain_result.rb, line 43
def as_hashes
  keys = explain_rows.shift.map(&:downcase)
  explain_rows.map { |values| Hash[keys.zip(values)].symbolize_keys! }
end
explain_rows() click to toggle source
# File lib/full_table_scan_matchers/db_adapters/mysql/explain_result.rb, line 48
def explain_rows
  @explain_rows ||= explained_result
    .reject { |row| row =~ /^\s*\+/ }        # Reject table frames, like: +----+-------------+
    .reject { |row| row =~ / rows? in set/ } # Reject "1 row in set" type things after result
    .map    { |row| row.split("|").map(&:strip).reject &:blank? }
end
explained_result() click to toggle source
# File lib/full_table_scan_matchers/db_adapters/mysql/explain_result.rb, line 55
def explained_result
  @explained_result ||= ActiveRecord::Base.connection.explain(sql_statement).split("\n")
end
offending_structs() click to toggle source
# File lib/full_table_scan_matchers/db_adapters/mysql/explain_result.rb, line 36
def offending_structs
  structs
    .reject  { |struct| struct.table == "NULL" }
    .select  { |struct| tables.nil? || Array(tables).map(&:to_s).include?(struct.table) }
    .select  { |struct| struct.key == "NULL" && struct.possible_keys == "NULL" }
end