query_reviewer 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +118 -0
- data/Rakefile +24 -0
- data/lib/query_reviewer/array_extensions.rb +29 -0
- data/lib/query_reviewer/controller_extensions.rb +65 -0
- data/lib/query_reviewer/mysql_adapter_extensions.rb +90 -0
- data/lib/query_reviewer/mysql_analyzer.rb +62 -0
- data/lib/query_reviewer/query_warning.rb +17 -0
- data/lib/query_reviewer/rails.rb +33 -0
- data/lib/query_reviewer/sql_query.rb +130 -0
- data/lib/query_reviewer/sql_query_collection.rb +103 -0
- data/lib/query_reviewer/sql_sub_query.rb +45 -0
- data/lib/query_reviewer/tasks.rb +8 -0
- data/lib/query_reviewer/views/_box.html.erb +11 -0
- data/lib/query_reviewer/views/_box_ajax.js +34 -0
- data/lib/query_reviewer/views/_box_body.html.erb +73 -0
- data/lib/query_reviewer/views/_box_disabled.html.erb +2 -0
- data/lib/query_reviewer/views/_box_header.html.erb +1 -0
- data/lib/query_reviewer/views/_box_includes.html.erb +234 -0
- data/lib/query_reviewer/views/_explain.html.erb +30 -0
- data/lib/query_reviewer/views/_js_includes.html.erb +68 -0
- data/lib/query_reviewer/views/_js_includes_new.html.erb +68 -0
- data/lib/query_reviewer/views/_profile.html.erb +26 -0
- data/lib/query_reviewer/views/_query_sql.html.erb +8 -0
- data/lib/query_reviewer/views/_query_trace.html.erb +31 -0
- data/lib/query_reviewer/views/_query_with_warning.html.erb +54 -0
- data/lib/query_reviewer/views/_spectrum.html.erb +10 -0
- data/lib/query_reviewer/views/_warning_no_query.html.erb +8 -0
- data/lib/query_reviewer/views/query_review_box_helper.rb +98 -0
- data/lib/query_reviewer.rb +54 -0
- data/query_reviewer_defaults.yml +39 -0
- metadata +96 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
<table>
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th>stage</th>
|
5
|
+
<th>duration</th>
|
6
|
+
<th>user cpu</th>
|
7
|
+
<th>context switches</th>
|
8
|
+
<th>block ops</th>
|
9
|
+
<th>messages</th>
|
10
|
+
<th>page faults</th>
|
11
|
+
</tr>
|
12
|
+
</thead>
|
13
|
+
<tbody>
|
14
|
+
<% query.profile.each do |profile| %>
|
15
|
+
<tr>
|
16
|
+
<td title="<%= h profile.Status %>"><%= h profile.Status %></td>
|
17
|
+
<td title="<%= h profile.Duration %> seconds"><%= h("%.4f" % profile.Duration.to_f) %>s</td>
|
18
|
+
<td title="USER: <%= profile.CPU_user.to_f %>s SYSTEM: <%= profile.CPU_system.to_f %>s"><%= h("%.4f" % profile.CPU_user.to_f) %>s</td>
|
19
|
+
<td title="Voluntary: <%= h profile.Context_voluntary %> Involuntary: <%= h profile.Context_involuntary %>"><%= h(profile.Context_voluntary.to_i + profile.Context_involuntary.to_i) %></td>
|
20
|
+
<td title="Ops in: <%= h profile.Block_ops_in %> Ops out: <%= h profile.Block_ops_out %>"><%= h(profile.Block_ops_in.to_i + profile.Block_ops_out.to_i) %></td>
|
21
|
+
<td title="Sent: <%= h profile.Messages_sent %> Received: <%= h profile.Messages_received %>"><%= h(profile.Messages_sent.to_i + profile.Messages_received.to_i) %></td>
|
22
|
+
<td title="Major: <%= h profile.Page_faults_major %> Minor: <%= h profile.Page_faults_minor %>"><%= h profile.Page_faults_major %></td>
|
23
|
+
<tr>
|
24
|
+
<% end %>
|
25
|
+
</tbody>
|
26
|
+
</table>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<span id="query_plain_sql_<%= query_sql.id %>" style="display: none;">
|
2
|
+
<%= syntax_highlighted_sql(query_sql.sql) %>
|
3
|
+
<% if query_sql.respond_to?(:subqueries) && query_sql.subqueries.length > 1 %>
|
4
|
+
<% end %>
|
5
|
+
</span>
|
6
|
+
<span id="query_sanitized_sql_<%= query_sql.id %>">
|
7
|
+
<%= syntax_highlighted_sql(query_sql.sanitized_sql) if query_sql.sanitized_sql %>
|
8
|
+
</span>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<div class="trace" id="trace_<%= query_id %>_abridged">
|
2
|
+
<code>
|
3
|
+
<% query_trace[0..(QueryReviewer::CONFIGURATION["stack_trace_lines"] - 1)].compact.each do |c| %>
|
4
|
+
<% if c.match(/:.*:/) %>
|
5
|
+
<% file = h(c.slice(0..(c.index(":", c.index(":")+1)-1))) %>
|
6
|
+
<span><%= file.split("/")[0..-2].join("/") %>/</span><span class="bold"><%= file.split("/").last %></span>
|
7
|
+
<br/>
|
8
|
+
<span class="indent"><%= h(c.slice((c.index(":", c.index(":")+1)+1)..-1)) %></span><br/>
|
9
|
+
<% else %>
|
10
|
+
<span><%= h c %></span><br/>
|
11
|
+
<% end %>
|
12
|
+
<% end %>
|
13
|
+
</code>
|
14
|
+
<a href="javascript: query_review_toggle('trace_<%= query_id %>_abridged'); query_review_toggle('trace_<%= query_id %>_full')" title="show full trace">FULL</a>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class="trace" style="display: none; max-height: 300px; overflow: scroll" id="trace_<%= query_id %>_full">
|
18
|
+
<code>
|
19
|
+
<% full_trace.compact.each do |c| %>
|
20
|
+
<% if c.match(/:.*:/) %>
|
21
|
+
<% file = h(c.slice(0..(c.index(":", c.index(":")+1)-1))) %>
|
22
|
+
<span><%= file.split("/")[0..-2].join("/") %>/</span><span class="bold"><%= file.split("/").last %></span>
|
23
|
+
<br/>
|
24
|
+
<span class="indent"><%= h(c.slice((c.index(":", c.index(":")+1)+1)..-1)) %></span><br/>
|
25
|
+
<% else %>
|
26
|
+
<span><%= h c %></span><br/>
|
27
|
+
<% end %>
|
28
|
+
<% end %>
|
29
|
+
</code>
|
30
|
+
<a href="javascript: query_review_toggle('trace_<%= query_id %>_abridged'); query_review_toggle('trace_<%= query_id %>_full')" title="show short trace">SHORT</a>
|
31
|
+
</div>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<li id="query_<%= query_with_warning.id %>">
|
2
|
+
<div>
|
3
|
+
<%= render :partial => "/spectrum", :locals => {:severity => query_with_warning.max_severity} %>
|
4
|
+
<% if QueryReviewer::CONFIGURATION["production_data"] %>
|
5
|
+
<div style="float: left; padding-right: 5px;">
|
6
|
+
<%= duration_with_color(query_with_warning) %>s
|
7
|
+
</div>
|
8
|
+
<% end %>
|
9
|
+
<p>
|
10
|
+
<% if query_with_warning.count > 1 %>
|
11
|
+
<b title="<%= query_with_warning.count %> queries were executed with the same stack trace and similar SQL structure">
|
12
|
+
<%= query_with_warning.count %> identical queries
|
13
|
+
</b>
|
14
|
+
<% end %>
|
15
|
+
<i>Table <%= (query_with_warning.warnings.detect {|w| !w.table.blank? } || query_with_warning.warnings.last).table %>:</i>
|
16
|
+
<% query_with_warning.warnings.sort{|a,b| a.severity <=> b.severity}.reverse.each_with_index do |warn, index| %>
|
17
|
+
<span style="color: <%= severity_color warn.severity%>;" title="<%= warn.desc%>"><%= warn.problem %></span><%= ", " if index < query_with_warning.warnings.length - 1 %>
|
18
|
+
<% end %>
|
19
|
+
<a href="javascript: query_review_toggle('warning_<%= query_with_warning.id %>_desc')" title="show/hide warning message">MSG</a>
|
20
|
+
<a href="javascript: query_review_toggle('warning_<%= query_with_warning.id %>_sql')" title="show/hide sql">SQL</a>
|
21
|
+
<% if query_with_warning.select? %>
|
22
|
+
<a href="javascript: query_review_toggle('warning_<%= query_with_warning.id %>_explain')" title="show/hide explain output">EXPLN</a>
|
23
|
+
<% end %>
|
24
|
+
<% if QueryReviewer::CONFIGURATION["profiling"] && query_with_warning.profile %>
|
25
|
+
<a href="javascript: query_review_toggle('warning_<%= query_with_warning.id %>_profile')" title="show/hide profile output">PROF</a>
|
26
|
+
<% end %>
|
27
|
+
<a href="javascript: query_review_toggle('warning_<%= query_with_warning.id %>_trace')" title="show/hide stack trace">TRACE</a>
|
28
|
+
<% if ignore_hash?(query_with_warning.to_hash) %>
|
29
|
+
<a href="javascript: remove_ignore_hash('<%= query_with_warning.to_hash %>'); query_review_hide('query_<%= query_with_warning.id %>')" title="stop ignore this query from now on">UNIGNR</a>
|
30
|
+
<% else %>
|
31
|
+
<a href="javascript: add_ignore_hash('<%= query_with_warning.to_hash %>'); query_review_hide('query_<%= query_with_warning.id %>')" title="ignoring this query from now on">IGNR</a>
|
32
|
+
<% end %>
|
33
|
+
</p>
|
34
|
+
</div>
|
35
|
+
<p style="display: none" id="warning_<%= query_with_warning.id %>_desc" class="indent">
|
36
|
+
<% query_with_warning.warnings.each do |warn| %>
|
37
|
+
<span style="color: <%= severity_color warn.severity%>"><%= warn.desc %></span><br/>
|
38
|
+
<% end %>
|
39
|
+
</p>
|
40
|
+
<p style="display: none" id="warning_<%= query_with_warning.id %>_sql" class="indent small tbpadded">
|
41
|
+
<%= render :partial => "/query_sql", :locals => {:query_sql => query_with_warning} %>
|
42
|
+
</p>
|
43
|
+
<div style="display: none" id="warning_<%= query_with_warning.id %>_explain" class="indent small tbpadded">
|
44
|
+
<%= render :partial => "/explain", :locals => {:query => query_with_warning} %>
|
45
|
+
</div>
|
46
|
+
<% if QueryReviewer::CONFIGURATION["profiling"] && query_with_warning.profile %>
|
47
|
+
<div style="display: none" id="warning_<%= query_with_warning.id %>_profile" class="indent small tbpadded">
|
48
|
+
<%= render :partial => "/profile", :locals => {:query => query_with_warning} %>
|
49
|
+
</div>
|
50
|
+
<% end %>
|
51
|
+
<div style="display: none" id="warning_<%= query_with_warning.id %>_trace" class="indent small">
|
52
|
+
<%= render :partial => "/query_trace", :locals => {:query_id => query_with_warning.id, :full_trace => query_with_warning.full_trace,:query_trace => query_with_warning.relevant_trace} %>
|
53
|
+
</div>
|
54
|
+
</li>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<div class="spectrum_container" title="Severity: <%= severity%> out of 10">
|
2
|
+
<% 0.upto(15) do |i| %>
|
3
|
+
<div class="spectrum_elem" style="background-color: <%= "##{i.to_s(16)}F0"%>"></div>
|
4
|
+
<% end %>
|
5
|
+
<% 0.upto(15) do |i| %>
|
6
|
+
<div class="spectrum_elem" style="background-color: <%= "#F#{((15-i)).to_s(16)}0"%>"></div>
|
7
|
+
<% end %>
|
8
|
+
<div class="spectrum_elem" style="background-color: #FF0000"></div>
|
9
|
+
<div class="spectrum_pointer" style="left: <%= severity * 3 + 2 %>px;"></div>
|
10
|
+
</div>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<li id="warning_<%= warning_no_query.id %>">
|
2
|
+
<div>
|
3
|
+
<%= render :partial => "/spectrum", :locals => {:severity => warning_no_query.severity} %>
|
4
|
+
<p>
|
5
|
+
<span style="color: <%= severity_color warning_no_query.severity%>" title="<%= warning_no_query.desc %>"><%= warning_no_query.problem %></span>
|
6
|
+
</p>
|
7
|
+
</div>
|
8
|
+
</li>
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module QueryReviewer
|
2
|
+
module Views
|
3
|
+
module QueryReviewBoxHelper
|
4
|
+
def parent_div_class
|
5
|
+
"sql_#{parent_div_status.downcase}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def parent_div_status
|
9
|
+
if !enabled_by_cookie
|
10
|
+
"DISABLED"
|
11
|
+
elsif overall_max_severity < (QueryReviewer::CONFIGURATION["warn_severity"] || 4)
|
12
|
+
"OK"
|
13
|
+
elsif overall_max_severity < (QueryReviewer::CONFIGURATION["critical_severity"] || 7)
|
14
|
+
# uh oh
|
15
|
+
"WARNING"
|
16
|
+
else
|
17
|
+
# oh @#&!
|
18
|
+
"CRITICAL"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def syntax_highlighted_sql(sql)
|
23
|
+
if QueryReviewer::CONFIGURATION["uv"]
|
24
|
+
uv_out = Uv.parse(sql, "xhtml", "sql_rails", false, "blackboard")
|
25
|
+
uv_out.gsub("<pre class=\"blackboard\">", "<code class=\"sql\">").gsub("</pre>", "</code>")
|
26
|
+
else
|
27
|
+
sql.gsub(/</, "<").gsub(/>/, ">")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def overall_max_severity
|
32
|
+
max = 0
|
33
|
+
max = queries_with_warnings_sorted_nonignored[0].max_severity unless queries_with_warnings_sorted_nonignored.empty?
|
34
|
+
max = warnings_no_query_sorted.first.severity unless warnings_no_query_sorted.empty? || warnings_no_query_sorted.first.severity < max
|
35
|
+
max
|
36
|
+
end
|
37
|
+
|
38
|
+
def severity_color(severity)
|
39
|
+
red = (severity * 16.0 / 10).to_i
|
40
|
+
green = ((10-severity) * 16.0 / 10).to_i
|
41
|
+
red = 8 if red > 8
|
42
|
+
red = 0 if red < 0
|
43
|
+
green = 8 if green > 8
|
44
|
+
green = 0 if green < 0
|
45
|
+
"##{red.to_s(16)}#{green.to_s(16)}0"
|
46
|
+
end
|
47
|
+
|
48
|
+
def ignore_hash?(h)
|
49
|
+
(controller.send(:cookies)["query_review_ignore_list"] || "").split(",").include?(h.to_s)
|
50
|
+
end
|
51
|
+
|
52
|
+
def queries_with_warnings
|
53
|
+
@queries.queries.select{|q| q.has_warnings?}
|
54
|
+
end
|
55
|
+
|
56
|
+
def queries_with_warnings_sorted
|
57
|
+
queries_with_warnings.sort{|a,b| (b.max_severity * 1000 + (b.duration || 0)) <=> (a.max_severity * 1000 + (a.duration || 0))}
|
58
|
+
end
|
59
|
+
|
60
|
+
def queries_with_warnings_sorted_nonignored
|
61
|
+
queries_with_warnings_sorted.select{|q| q.max_severity >= ::QueryReviewer::CONFIGURATION["warn_severity"] && !ignore_hash?(q.to_hash)}
|
62
|
+
end
|
63
|
+
|
64
|
+
def queries_with_warnings_sorted_ignored
|
65
|
+
queries_with_warnings_sorted.reject{|q| q.max_severity >= ::QueryReviewer::CONFIGURATION["warn_severity"] && !ignore_hash?(q.to_hash)}
|
66
|
+
end
|
67
|
+
|
68
|
+
def warnings_no_query_sorted
|
69
|
+
@queries.collection_warnings.sort{|a,b| a.severity <=> b.severity}.reverse
|
70
|
+
end
|
71
|
+
|
72
|
+
def warnings_no_query_sorted_ignored
|
73
|
+
warnings_no_query_sorted.select{|q| q.severity < ::QueryReviewer::CONFIGURATION["warn_severity"]}
|
74
|
+
end
|
75
|
+
|
76
|
+
def warnings_no_query_sorted_nonignored
|
77
|
+
warnings_no_query_sorted.select{|q| q.severity >= ::QueryReviewer::CONFIGURATION["warn_severity"]}
|
78
|
+
end
|
79
|
+
|
80
|
+
def enabled_by_cookie
|
81
|
+
controller.send(:cookies)["query_review_enabled"]
|
82
|
+
end
|
83
|
+
|
84
|
+
def duration_with_color(query)
|
85
|
+
title = query.duration_stats
|
86
|
+
duration = query.duration
|
87
|
+
span_html = if duration > QueryReviewer::CONFIGURATION["critical_duration_threshold"]
|
88
|
+
"<span style=\"color: #{severity_color(9)}\" title=\"#{title}\">#{"%.3f" % duration}</span>"
|
89
|
+
elsif duration > QueryReviewer::CONFIGURATION["warn_duration_threshold"]
|
90
|
+
"<span style=\"color: #{severity_color(QueryReviewer::CONFIGURATION["critical_severity"])}\" title=\"#{title}\">#{"%.3f" % duration}</span>"
|
91
|
+
else
|
92
|
+
"<span title=\"#{title}\">#{"%.3f" % duration}</span>"
|
93
|
+
end
|
94
|
+
span_html.respond_to?(:html_safe) ? span_html.html_safe : span_html
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# QueryReviewer
|
2
|
+
require "ostruct"
|
3
|
+
require 'erb'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
module QueryReviewer
|
7
|
+
CONFIGURATION = {}
|
8
|
+
|
9
|
+
def self.load_configuration
|
10
|
+
default_config = YAML::load(ERB.new(IO.read(File.join(File.dirname(__FILE__), "..", "query_reviewer_defaults.yml"))).result)
|
11
|
+
|
12
|
+
CONFIGURATION.merge!(default_config["all"] || {})
|
13
|
+
CONFIGURATION.merge!(default_config[Rails.env || "test"] || {})
|
14
|
+
|
15
|
+
app_config_file = File.join(Rails.root.to_s, "config", "query_reviewer.yml")
|
16
|
+
|
17
|
+
if File.exist?(app_config_file)
|
18
|
+
app_config = YAML.load(ERB.new(IO.read(app_config_file)).result)
|
19
|
+
CONFIGURATION.merge!(app_config["all"] || {})
|
20
|
+
CONFIGURATION.merge!(app_config[Rails.env || "test"] || {})
|
21
|
+
end
|
22
|
+
|
23
|
+
if enabled?
|
24
|
+
begin
|
25
|
+
CONFIGURATION["uv"] ||= !Gem.searcher.find("uv").nil?
|
26
|
+
if CONFIGURATION["uv"]
|
27
|
+
require "uv"
|
28
|
+
end
|
29
|
+
rescue
|
30
|
+
CONFIGURATION["uv"] ||= false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.enabled?
|
36
|
+
CONFIGURATION["enabled"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
QueryReviewer.load_configuration
|
41
|
+
|
42
|
+
if QueryReviewer.enabled?
|
43
|
+
require "query_reviewer/query_warning"
|
44
|
+
require "query_reviewer/array_extensions"
|
45
|
+
require "query_reviewer/sql_query"
|
46
|
+
require "query_reviewer/mysql_analyzer"
|
47
|
+
require "query_reviewer/sql_sub_query"
|
48
|
+
require "query_reviewer/mysql_adapter_extensions"
|
49
|
+
require "query_reviewer/controller_extensions"
|
50
|
+
require "query_reviewer/sql_query_collection"
|
51
|
+
end
|
52
|
+
|
53
|
+
# Rails Integration
|
54
|
+
require 'query_reviewer/rails' if defined?(Rails)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
all:
|
2
|
+
inject_view: true
|
3
|
+
stack_trace_lines: 3
|
4
|
+
trace_includes_vendor: false
|
5
|
+
trace_includes_lib: true
|
6
|
+
profiling: enabled
|
7
|
+
production_data: true
|
8
|
+
max_safe_key_length: 100
|
9
|
+
disable_sql_cache: true
|
10
|
+
|
11
|
+
warn_severity: 3
|
12
|
+
critical_severity: 7
|
13
|
+
|
14
|
+
warn_select_count: 20
|
15
|
+
critical_select_count: 50
|
16
|
+
|
17
|
+
warn_update_count: 5
|
18
|
+
critical_update_count: 10
|
19
|
+
|
20
|
+
warn_insert_count: 5
|
21
|
+
critical_insert_count: 10
|
22
|
+
|
23
|
+
warn_delete_count: 5
|
24
|
+
critical_delete_count: 10
|
25
|
+
|
26
|
+
warn_duration_threshold: 0.2
|
27
|
+
critical_duration_threshold: 1.0
|
28
|
+
|
29
|
+
warn_affected_rows: 10
|
30
|
+
critical_affected_rows: 100
|
31
|
+
|
32
|
+
development:
|
33
|
+
enabled: true
|
34
|
+
|
35
|
+
production:
|
36
|
+
enabled: false
|
37
|
+
|
38
|
+
test:
|
39
|
+
enabled: false
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: query_reviewer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 9
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: "0.1"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- dsboulder
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-19 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Runs explain before each select query and displays results in an overlayed div
|
22
|
+
email: nesquena@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- MIT-LICENSE
|
31
|
+
- Rakefile
|
32
|
+
- README.md
|
33
|
+
- query_reviewer_defaults.yml
|
34
|
+
- lib/query_reviewer/array_extensions.rb
|
35
|
+
- lib/query_reviewer/controller_extensions.rb
|
36
|
+
- lib/query_reviewer/mysql_adapter_extensions.rb
|
37
|
+
- lib/query_reviewer/mysql_analyzer.rb
|
38
|
+
- lib/query_reviewer/query_warning.rb
|
39
|
+
- lib/query_reviewer/rails.rb
|
40
|
+
- lib/query_reviewer/sql_query.rb
|
41
|
+
- lib/query_reviewer/sql_query_collection.rb
|
42
|
+
- lib/query_reviewer/sql_sub_query.rb
|
43
|
+
- lib/query_reviewer/tasks.rb
|
44
|
+
- lib/query_reviewer/views/_box.html.erb
|
45
|
+
- lib/query_reviewer/views/_box_ajax.js
|
46
|
+
- lib/query_reviewer/views/_box_body.html.erb
|
47
|
+
- lib/query_reviewer/views/_box_disabled.html.erb
|
48
|
+
- lib/query_reviewer/views/_box_header.html.erb
|
49
|
+
- lib/query_reviewer/views/_box_includes.html.erb
|
50
|
+
- lib/query_reviewer/views/_explain.html.erb
|
51
|
+
- lib/query_reviewer/views/_js_includes.html.erb
|
52
|
+
- lib/query_reviewer/views/_js_includes_new.html.erb
|
53
|
+
- lib/query_reviewer/views/_profile.html.erb
|
54
|
+
- lib/query_reviewer/views/_query_sql.html.erb
|
55
|
+
- lib/query_reviewer/views/_query_trace.html.erb
|
56
|
+
- lib/query_reviewer/views/_query_with_warning.html.erb
|
57
|
+
- lib/query_reviewer/views/_spectrum.html.erb
|
58
|
+
- lib/query_reviewer/views/_warning_no_query.html.erb
|
59
|
+
- lib/query_reviewer/views/query_review_box_helper.rb
|
60
|
+
- lib/query_reviewer.rb
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: https://github.com/nesquena/query_reviewer
|
63
|
+
licenses: []
|
64
|
+
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.3.7
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Runs explain before each select query and displays results in an overlayed div
|
95
|
+
test_files: []
|
96
|
+
|