sql_query_analyzer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ab9aa8ae033ce267111f508bfa46c9d18fb4b50da0f8dc175719ab40a4a416eb
|
4
|
+
data.tar.gz: f6a8db3ac983476c5c26893a76f4ac127bf83a1fae1172df3f76618e2865752b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7013b5496ff18a4753095df4850d3f6130567376a7157fc261848b56a970679c1da2aa55bfaf47f7423af5a4c4ad101e659137ee198342e7a291e2ea28fa25bf
|
7
|
+
data.tar.gz: 4f82e5a2bac1d408dfc9eb40f5b424125cedad911102790d81509a25e102e02fa12ed4da47efa97c360d920030ecdbf9dd320100e4cd9b9d9484ef7d3e7c39b1
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# lib/sql_query_analyzer/explain_analyzer.rb
|
2
|
+
module SqlQueryAnalyzer
|
3
|
+
module ExplainAnalyzer
|
4
|
+
def explain_with_suggestions
|
5
|
+
explain_output = explain(analyze: true, verbose: true, costs: true, buffers: true, timing: true)
|
6
|
+
|
7
|
+
engine = SqlQueryAnalyzer::SuggestionEngine.new(explain_output, to_sql)
|
8
|
+
suggestions = engine.analyze
|
9
|
+
|
10
|
+
puts "\n=== EXPLAIN ANALYZE OUTPUT ===\n"
|
11
|
+
puts explain_output
|
12
|
+
puts "\n=== SUGGESTIONS ===\n"
|
13
|
+
suggestions.each do |suggestion|
|
14
|
+
puts "[#{suggestion.severity.to_s.upcase}] #{suggestion.message}"
|
15
|
+
end
|
16
|
+
rescue => e
|
17
|
+
puts "Error analyzing query: #{e.message}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Monkey patch it in Rails
|
23
|
+
ActiveSupport.on_load(:active_record) do
|
24
|
+
ActiveRecord::Relation.include(SqlQueryAnalyzer::ExplainAnalyzer)
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# lib/sql_query_analyzer/suggestion_engine.rb
|
2
|
+
module SqlQueryAnalyzer
|
3
|
+
class Suggestion
|
4
|
+
attr_reader :severity, :message
|
5
|
+
|
6
|
+
def initialize(severity, message)
|
7
|
+
@severity = severity
|
8
|
+
@message = message
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class SuggestionEngine
|
13
|
+
def initialize(explain_output, sql = nil)
|
14
|
+
@explain_output = explain_output
|
15
|
+
@sql = sql
|
16
|
+
end
|
17
|
+
|
18
|
+
def analyze
|
19
|
+
suggestions = []
|
20
|
+
|
21
|
+
# Rule 1: Sequential Scan
|
22
|
+
if @explain_output.match?(/Seq Scan/i)
|
23
|
+
suggestions << Suggestion.new(:critical, "⚡ Sequential Scan detected. Consider adding indexes to avoid full table scans.")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Rule 2: SELECT *
|
27
|
+
if @sql&.match?(/select\s+\*/i)
|
28
|
+
suggestions << Suggestion.new(:warning, "🚨 Query uses SELECT *. Selecting only needed columns is more efficient.")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Rule 3: Sort operation
|
32
|
+
if @explain_output.match?(/Sort/i)
|
33
|
+
suggestions << Suggestion.new(:info, "📈 Sort detected. Consider adding an index to support ORDER BY.")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Rule 4: Missing JOIN conditions
|
37
|
+
if @sql&.match?(/join/i) && !@sql.match?(/on/i)
|
38
|
+
suggestions << Suggestion.new(:critical, "⚡ JOIN without ON detected. May cause massive row combinations (CROSS JOIN).")
|
39
|
+
end
|
40
|
+
|
41
|
+
# Rule 5: High Rows estimation
|
42
|
+
if @explain_output.match?(/rows=(\d+)/)
|
43
|
+
rows = @explain_output.match(/rows=(\d+)/)[1].to_i
|
44
|
+
if rows > 100_000
|
45
|
+
suggestions << Suggestion.new(:critical, "🔥 High number of rows (#{rows}). Consider using WHERE conditions or LIMIT.")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
suggestions
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# lib/sql_query_analyzer.rb
|
2
|
+
require "active_support"
|
3
|
+
require "active_record"
|
4
|
+
|
5
|
+
require "sql_query_analyzer/version"
|
6
|
+
require "sql_query_analyzer/suggestion_engine"
|
7
|
+
require "sql_query_analyzer/explain_analyzer"
|
8
|
+
|
9
|
+
module SqlQueryAnalyzer
|
10
|
+
# Future configurations can go here
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sql_query_analyzer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anoob Bava
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-04-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.13'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.13'
|
27
|
+
description: A Ruby on Rails gem that analyzes SQL queries and suggests optimizations
|
28
|
+
like missing indexes, inefficient sorts, and risky joins.
|
29
|
+
email:
|
30
|
+
- anoob.bava@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- lib/sql_query_analyzer.rb
|
36
|
+
- lib/sql_query_analyzer/explain_analyzer.rb
|
37
|
+
- lib/sql_query_analyzer/suggestion_engine.rb
|
38
|
+
- lib/sql_query_analyzer/version.rb
|
39
|
+
homepage: https://github.com/anoobbava/sql_query_analyzer
|
40
|
+
licenses:
|
41
|
+
- MIT
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubygems_version: 3.2.33
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Explain ActiveRecord queries and get optimization suggestions.
|
62
|
+
test_files: []
|