rdavila-query_reviewer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README +51 -0
- data/Rakefile +22 -0
- data/init.rb +13 -0
- data/lib/query_reviewer.rb +51 -0
- data/lib/query_reviewer/array_extensions.rb +29 -0
- data/lib/query_reviewer/controller_extensions.rb +60 -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/sql_query.rb +130 -0
- data/lib/query_reviewer/sql_query_collection.rb +103 -0
- data/lib/query_reviewer/sql_sub_query.rb +44 -0
- data/lib/query_reviewer/views/_box.rhtml +11 -0
- data/lib/query_reviewer/views/_box_ajax.js +34 -0
- data/lib/query_reviewer/views/_box_body.rhtml +73 -0
- data/lib/query_reviewer/views/_box_disabled.rhtml +2 -0
- data/lib/query_reviewer/views/_box_header.rhtml +1 -0
- data/lib/query_reviewer/views/_box_includes.rhtml +297 -0
- data/lib/query_reviewer/views/_explain.rhtml +30 -0
- data/lib/query_reviewer/views/_profile.rhtml +26 -0
- data/lib/query_reviewer/views/_query_sql.rhtml +8 -0
- data/lib/query_reviewer/views/_query_trace.rhtml +31 -0
- data/lib/query_reviewer/views/_query_with_warning.rhtml +54 -0
- data/lib/query_reviewer/views/_spectrum.rhtml +10 -0
- data/lib/query_reviewer/views/_warning_no_query.rhtml +8 -0
- data/lib/query_reviewer/views/query_review_box_helper.rb +97 -0
- data/query_reviewer_defaults.yml +39 -0
- data/rails/init.rb +13 -0
- data/tasks/query_reviewer_tasks.rake +7 -0
- data/test/sql_query_test.rb +8 -0
- data/test/sql_sub_query_test.rb +17 -0
- data/test/test_helper.rb +18 -0
- metadata +97 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
<table class="explain">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th>table</th>
|
5
|
+
<th>select_type</th>
|
6
|
+
<th>type</th>
|
7
|
+
<th>extra</th>
|
8
|
+
<th>possible_keys</th>
|
9
|
+
<th>key</th>
|
10
|
+
<th>key length</th>
|
11
|
+
<th>ref</th>
|
12
|
+
<th>rows</th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
<tbody>
|
16
|
+
<% query.subqueries.each do |subquery| %>
|
17
|
+
<tr>
|
18
|
+
<td title="<%= h subquery.table %>"><%= h subquery.table %></td>
|
19
|
+
<td title="<%= h subquery.select_type %>"><%= h subquery.select_type %></td>
|
20
|
+
<td title="<%= h subquery.query_type %>"><%= h subquery.query_type %></td>
|
21
|
+
<td title="<%= h subquery.extra %>"><%= h subquery.extra %></td>
|
22
|
+
<td title="<%= h subquery.possible_keys %>"><%= h subquery.possible_keys %></td>
|
23
|
+
<td title="<%= h subquery.key %>"><%= h subquery.key %></td>
|
24
|
+
<td title="<%= h subquery.key_len %>"><%= h subquery.key_len %></td>
|
25
|
+
<td title="<%= h subquery.ref %>"><%= h subquery.ref %></td>
|
26
|
+
<td title="<%= h subquery.rows %>"><%= h subquery.rows %></td>
|
27
|
+
</tr>
|
28
|
+
<% end %>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
@@ -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", :object => 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", :object => query_with_warning.relevant_trace, :locals => {:query_id => query_with_warning.id, :full_trace => query_with_warning.full_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,97 @@
|
|
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
|
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
|
+
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
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -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
|
data/rails/init.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Include hook code here
|
2
|
+
|
3
|
+
require 'query_reviewer'
|
4
|
+
|
5
|
+
if QueryReviewer.enabled?
|
6
|
+
ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:include, QueryReviewer::MysqlAdapterExtensions)
|
7
|
+
ActionController::Base.send(:include, QueryReviewer::ControllerExtensions)
|
8
|
+
Array.send(:include, QueryReviewer::ArrayExtensions)
|
9
|
+
|
10
|
+
if ActionController::Base.respond_to?(:append_view_path)
|
11
|
+
ActionController::Base.append_view_path(File.dirname(__FILE__) + "/lib/query_reviewer/views")
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# desc "Explaining what the task does"
|
2
|
+
namespace :query_reviewer do
|
3
|
+
desc "Create a default config/query_reviewer.yml"
|
4
|
+
task :setup do
|
5
|
+
FileUtils.copy(File.join(File.dirname(__FILE__), "..", "query_reviewer_defaults.yml"), File.join(RAILS_ROOT, "config", "query_reviewer.yml"))
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class SqlSubqueryTest < Test::Unit::TestCase
|
4
|
+
def test_analyze_select_type
|
5
|
+
query = get_query(:select_type => "DEPENDENT UNION")
|
6
|
+
query.send :analyze_select_type!
|
7
|
+
query.should_warn("DEPENDENT UNION", 2)
|
8
|
+
|
9
|
+
query = get_query(:select_type => "UNCACHEABLE SUBQUERY")
|
10
|
+
query.send :analyze_select_type!
|
11
|
+
query.should_warn("UNCACHEABLE SUBQUERY", 10)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_query(options)
|
15
|
+
SqlSubQuery.new(options)
|
16
|
+
end
|
17
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "activesupport"
|
3
|
+
require 'test/unit'
|
4
|
+
require "query_reviewer"
|
5
|
+
|
6
|
+
module QueryReviewer
|
7
|
+
class SqlSubQuery
|
8
|
+
include Test::Unit::Assertions
|
9
|
+
def should_warn(problem, severity = nil)
|
10
|
+
assert self.warnings.detect{|warn| warn.problem.downcase == problem.downcase &&
|
11
|
+
(!severity || warn.severity == severity)}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Test::Unit::TestCase
|
17
|
+
include QueryReviewer
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rdavila-query_reviewer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Kongregate
|
13
|
+
- David Stevenson
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-04-26 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: |
|
23
|
+
This rails plugin not only runs "EXPLAIN" before each of your select queries in development, but provides a small DIV in the rendered output of each page with the summary of query warnings that it analyzed.
|
24
|
+
|
25
|
+
email: rdavila84@gmail.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- MIT-LICENSE
|
34
|
+
- query_reviewer_defaults.yml
|
35
|
+
- Rakefile
|
36
|
+
- README
|
37
|
+
- init.rb
|
38
|
+
- lib/query_reviewer/sql_sub_query.rb
|
39
|
+
- lib/query_reviewer/array_extensions.rb
|
40
|
+
- lib/query_reviewer/views/_box_ajax.js
|
41
|
+
- lib/query_reviewer/views/_query_sql.rhtml
|
42
|
+
- lib/query_reviewer/views/_query_with_warning.rhtml
|
43
|
+
- lib/query_reviewer/views/_box_disabled.rhtml
|
44
|
+
- lib/query_reviewer/views/_explain.rhtml
|
45
|
+
- lib/query_reviewer/views/_query_trace.rhtml
|
46
|
+
- lib/query_reviewer/views/_box_includes.rhtml
|
47
|
+
- lib/query_reviewer/views/_box.rhtml
|
48
|
+
- lib/query_reviewer/views/_box_body.rhtml
|
49
|
+
- lib/query_reviewer/views/_box_header.rhtml
|
50
|
+
- lib/query_reviewer/views/_profile.rhtml
|
51
|
+
- lib/query_reviewer/views/_spectrum.rhtml
|
52
|
+
- lib/query_reviewer/views/query_review_box_helper.rb
|
53
|
+
- lib/query_reviewer/views/_warning_no_query.rhtml
|
54
|
+
- lib/query_reviewer/mysql_adapter_extensions.rb
|
55
|
+
- lib/query_reviewer/query_warning.rb
|
56
|
+
- lib/query_reviewer/controller_extensions.rb
|
57
|
+
- lib/query_reviewer/mysql_analyzer.rb
|
58
|
+
- lib/query_reviewer/sql_query.rb
|
59
|
+
- lib/query_reviewer/sql_query_collection.rb
|
60
|
+
- lib/query_reviewer.rb
|
61
|
+
- rails/init.rb
|
62
|
+
- tasks/query_reviewer_tasks.rake
|
63
|
+
- test/test_helper.rb
|
64
|
+
- test/sql_sub_query_test.rb
|
65
|
+
- test/sql_query_test.rb
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/dsboulder/query_reviewer
|
68
|
+
licenses: []
|
69
|
+
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.3.6
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: An advanced mysql query analyzer for rails
|
96
|
+
test_files: []
|
97
|
+
|