Skip to content

Commit

Permalink
Merge pull request #206 from cturner/master
Browse files Browse the repository at this point in the history
Updated MySQL JDBC adapter to support Rails 3.2 explain feature
  • Loading branch information
nicksieger committed Jul 28, 2012
2 parents 02fa182 + f69f00b commit 86af261
Showing 1 changed file with 81 additions and 0 deletions.
81 changes: 81 additions & 0 deletions lib/arjdbc/mysql/adapter.rb
Expand Up @@ -466,6 +466,87 @@ def initialize(*args)
configure_connection
end

## EXPLAIN support lifted from the mysql2 gem with slight modifications
## to work in the JDBC adapter gem.
def supports_explain?
true
end

def explain(arel, binds = [])
sql = "EXPLAIN #{to_sql(arel, binds.dup)}"
start = Time.now.to_f
raw_result = execute(sql, "EXPLAIN")
ar_result = ActiveRecord::Result.new(raw_result[0].keys, raw_result)
elapsed = Time.now.to_f - start
ExplainPrettyPrinter.new.pp(ar_result, elapsed)
end

class ExplainPrettyPrinter # :nodoc:
# Pretty prints the result of a EXPLAIN in a way that resembles the output of the
# MySQL shell:
#
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
# | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
# | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
# | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
# 2 rows in set (0.00 sec)
#
# This is an exercise in Ruby hyperrealism :).
def pp(result, elapsed)
widths = compute_column_widths(result)
separator = build_separator(widths)

pp = []

pp << separator
pp << build_cells(result.columns, widths)
pp << separator

result.rows.each do |row|
pp << build_cells(row.values, widths)
end

pp << separator
pp << build_footer(result.rows.length, elapsed)

pp.join("\n") + "\n"
end

private

def compute_column_widths(result)
[].tap do |widths|
result.columns.each do |col|
cells_in_column = [col] + result.rows.map {|r| r[col].nil? ? 'NULL' : r[col].to_s}
widths << cells_in_column.map(&:length).max
end
end

end

def build_separator(widths)
padding = 1
'+' + widths.map {|w| '-' * (w + (padding*2))}.join('+') + '+'
end

def build_cells(items, widths)
cells = []
items.each_with_index do |item, i|
item = 'NULL' if item.nil?
justifier = item.is_a?(Numeric) ? 'rjust' : 'ljust'
cells << item.to_s.send(justifier, widths[i])
end
'| ' + cells.join(' | ') + ' |'
end

def build_footer(nrows, elapsed)
rows_label = nrows == 1 ? 'row' : 'rows'
"#{nrows} #{rows_label} in set (%.2f sec)" % elapsed
end
end

def jdbc_connection_class(spec)
::ArJdbc::MySQL.jdbc_connection_class
end
Expand Down

0 comments on commit 86af261

Please sign in to comment.