class Eyeballs::Inspector

Constants

FORMATS
OPTIONS

Public Class Methods

new(relation) click to toggle source
# File lib/eyeballs/inspector.rb, line 9
def initialize(relation)
  @relation = relation
end

Public Instance Methods

explain(format: :text, options: OPTIONS) click to toggle source
# File lib/eyeballs/inspector.rb, line 13
def explain(format: :text, options: OPTIONS)
  @explain ||= explain_queries(format: format, options: options).map do |query|
    run_query(query)
  end
end
explain_queries(format: :text, options: OPTIONS) click to toggle source
# File lib/eyeballs/inspector.rb, line 19
def explain_queries(format: :text, options: OPTIONS)
  validate_format!(format)
  validate_options!(options)
  @explain_queries ||= queries.map do |query|
    explain_query(query, format, options)
  end
end
gocmdpev() click to toggle source
# File lib/eyeballs/inspector.rb, line 54
def gocmdpev
  to_hash_array.each do |h|
    begin
      tmp = Tempfile.new('pg-eyeballs')
      tmp.write(h.to_json)
      tmp.close
      system("cat #{tmp.path} | gocmdpev")
    ensure
      tmp.close
      tmp.unlink
    end
  end
  nil
end
inspect() click to toggle source
# File lib/eyeballs/inspector.rb, line 45
def inspect
  "Eyeballs::Inspector: #{@relation.to_s}"
end
log_json(options: OPTIONS) click to toggle source
# File lib/eyeballs/inspector.rb, line 49
def log_json(options: OPTIONS)
  to_hash_array.each { |h| puts "#{h.to_json }" }
  nil
end
queries() click to toggle source
# File lib/eyeballs/inspector.rb, line 27
def queries
  @relation.connection.to_sql(query_array).map { |query|
    build_sql(query)
  }
end
to_hash_array(options: OPTIONS) click to toggle source
# File lib/eyeballs/inspector.rb, line 41
def to_hash_array(options: OPTIONS)
  to_json(options: options).map { |json| JSON.parse(json) }
end
to_json(options: OPTIONS) click to toggle source
# File lib/eyeballs/inspector.rb, line 37
def to_json(options: OPTIONS)
  explain(options: options, format: :json)
end
to_s(options: OPTIONS) click to toggle source
# File lib/eyeballs/inspector.rb, line 33
def to_s(options: OPTIONS)
  explain.join("\n\n")
end

Private Instance Methods

build_sql(query_binding) click to toggle source
# File lib/eyeballs/inspector.rb, line 103
def build_sql(query_binding)
  query_binding[1].each.with_index.reduce(query_binding[0]) do |sql,(value, index)|
    sql.sub("$#{index + 1}", @relation.connection.quote(extract_value(value)))
  end
end
explain_options(format, options) click to toggle source
# File lib/eyeballs/inspector.rb, line 95
def explain_options(format, options)
  options.map(&:upcase).tap { |a| a << "FORMAT #{format.upcase}" }.join(',')
end
explain_query(query, format, options) click to toggle source
# File lib/eyeballs/inspector.rb, line 91
def explain_query(query, format, options)
  "EXPLAIN (#{explain_options(format, options)}) #{query}"
end
extract_value(value) click to toggle source
# File lib/eyeballs/inspector.rb, line 109
def extract_value(value)
  if value.is_a?(Array) #Rails 4
    value.last
  elsif value.is_a?(ActiveRecord::Relation::QueryAttribute) #Rails 5
    value.value
  end
end
query_array() click to toggle source
# File lib/eyeballs/inspector.rb, line 71
def query_array
  @relation.send(:collecting_queries_for_explain) do
    @relation.send(:exec_queries)
  end
end
run_query(sql) click to toggle source
# File lib/eyeballs/inspector.rb, line 99
def run_query(sql)
  @relation.connection.raw_connection.exec(sql).values.join("\n")
end
validate_format!(format) click to toggle source
# File lib/eyeballs/inspector.rb, line 77
def validate_format!(format)
  unless FORMATS.include?(format)
    raise Eyeballs::UnknownFormatError, "Unknown Format #{format}"
  end
end
validate_options!(options) click to toggle source
# File lib/eyeballs/inspector.rb, line 83
def validate_options!(options)
  options.each do |option|
    unless OPTIONS.include?(option)
      raise Eyeballs::UnknownOptionError, "Unknown Option #{option}"
    end
  end
end