mysql_genius 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 +7 -0
- data/.github/workflows/ci.yml +53 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +21 -0
- data/README.md +295 -0
- data/Rakefile +6 -0
- data/app/controllers/concerns/mysql_genius/ai_features.rb +360 -0
- data/app/controllers/concerns/mysql_genius/database_analysis.rb +259 -0
- data/app/controllers/concerns/mysql_genius/query_execution.rb +129 -0
- data/app/controllers/mysql_genius/base_controller.rb +18 -0
- data/app/controllers/mysql_genius/queries_controller.rb +54 -0
- data/app/services/mysql_genius/ai_client.rb +84 -0
- data/app/services/mysql_genius/ai_optimization_service.rb +56 -0
- data/app/services/mysql_genius/ai_suggestion_service.rb +56 -0
- data/app/views/layouts/mysql_genius/application.html.erb +116 -0
- data/app/views/mysql_genius/queries/_shared_results.html.erb +56 -0
- data/app/views/mysql_genius/queries/_tab_ai_tools.html.erb +43 -0
- data/app/views/mysql_genius/queries/_tab_duplicate_indexes.html.erb +24 -0
- data/app/views/mysql_genius/queries/_tab_query_stats.html.erb +36 -0
- data/app/views/mysql_genius/queries/_tab_server.html.erb +54 -0
- data/app/views/mysql_genius/queries/_tab_slow_queries.html.erb +17 -0
- data/app/views/mysql_genius/queries/_tab_sql_query.html.erb +40 -0
- data/app/views/mysql_genius/queries/_tab_table_sizes.html.erb +31 -0
- data/app/views/mysql_genius/queries/_tab_unused_indexes.html.erb +25 -0
- data/app/views/mysql_genius/queries/_tab_visual_builder.html.erb +61 -0
- data/app/views/mysql_genius/queries/index.html.erb +1185 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/routes.rb +24 -0
- data/docs/screenshots/ai_tools.png +0 -0
- data/docs/screenshots/duplicate_indexes.png +0 -0
- data/docs/screenshots/query_stats.png +0 -0
- data/docs/screenshots/server.png +0 -0
- data/docs/screenshots/sql_query.png +0 -0
- data/docs/screenshots/table_sizes.png +0 -0
- data/docs/screenshots/visual_builder.png +0 -0
- data/lib/mysql_genius/configuration.rb +96 -0
- data/lib/mysql_genius/engine.rb +12 -0
- data/lib/mysql_genius/slow_query_monitor.rb +38 -0
- data/lib/mysql_genius/sql_validator.rb +55 -0
- data/lib/mysql_genius/version.rb +3 -0
- data/lib/mysql_genius.rb +23 -0
- data/mysql_genius.gemspec +34 -0
- metadata +122 -0
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "mysql_genius"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/config/routes.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MysqlGenius::Engine.routes.draw do
|
|
2
|
+
root to: "queries#index"
|
|
3
|
+
|
|
4
|
+
get "columns", to: "queries#columns"
|
|
5
|
+
post "execute", to: "queries#execute"
|
|
6
|
+
post "explain", to: "queries#explain"
|
|
7
|
+
post "suggest", to: "queries#suggest"
|
|
8
|
+
post "optimize", to: "queries#optimize"
|
|
9
|
+
get "slow_queries", to: "queries#slow_queries"
|
|
10
|
+
get "duplicate_indexes", to: "queries#duplicate_indexes"
|
|
11
|
+
get "table_sizes", to: "queries#table_sizes"
|
|
12
|
+
get "query_stats", to: "queries#query_stats"
|
|
13
|
+
get "unused_indexes", to: "queries#unused_indexes"
|
|
14
|
+
get "server_overview", to: "queries#server_overview"
|
|
15
|
+
|
|
16
|
+
# AI features
|
|
17
|
+
post "describe_query", to: "queries#describe_query"
|
|
18
|
+
post "schema_review", to: "queries#schema_review"
|
|
19
|
+
post "rewrite_query", to: "queries#rewrite_query"
|
|
20
|
+
post "index_advisor", to: "queries#index_advisor"
|
|
21
|
+
post "anomaly_detection", to: "queries#anomaly_detection"
|
|
22
|
+
post "root_cause", to: "queries#root_cause"
|
|
23
|
+
post "migration_risk", to: "queries#migration_risk"
|
|
24
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module MysqlGenius
|
|
2
|
+
class Configuration
|
|
3
|
+
# Tables to feature in the visual builder dropdown (array of strings).
|
|
4
|
+
# When empty, all non-blocked tables are shown.
|
|
5
|
+
attr_accessor :featured_tables
|
|
6
|
+
|
|
7
|
+
# Tables that must never be queried (auth, sessions, internal Rails tables).
|
|
8
|
+
attr_accessor :blocked_tables
|
|
9
|
+
|
|
10
|
+
# Column name patterns to mask with [REDACTED] in query results.
|
|
11
|
+
# Matched case-insensitively via String#include?.
|
|
12
|
+
attr_accessor :masked_column_patterns
|
|
13
|
+
|
|
14
|
+
# Default columns to check in the visual builder, keyed by table name.
|
|
15
|
+
# Example: { "users" => %w[id name email created_at] }
|
|
16
|
+
attr_accessor :default_columns
|
|
17
|
+
|
|
18
|
+
# Maximum rows a single query can return.
|
|
19
|
+
attr_accessor :max_row_limit
|
|
20
|
+
|
|
21
|
+
# Default row limit when none is specified.
|
|
22
|
+
attr_accessor :default_row_limit
|
|
23
|
+
|
|
24
|
+
# Query timeout in milliseconds.
|
|
25
|
+
attr_accessor :query_timeout_ms
|
|
26
|
+
|
|
27
|
+
# Proc that receives the controller instance and returns true if the user
|
|
28
|
+
# is authorized. Example:
|
|
29
|
+
# config.authenticate = ->(controller) { controller.current_user&.admin? }
|
|
30
|
+
attr_accessor :authenticate
|
|
31
|
+
|
|
32
|
+
# AI configuration — set to nil to disable AI features entirely.
|
|
33
|
+
# Must respond to :call(messages:, response_format:, temperature:)
|
|
34
|
+
# and return a Hash with "choices" in OpenAI-compatible format,
|
|
35
|
+
# OR set ai_endpoint + ai_api_key for a direct OpenAI-compatible HTTP API.
|
|
36
|
+
attr_accessor :ai_client
|
|
37
|
+
attr_accessor :ai_endpoint
|
|
38
|
+
attr_accessor :ai_api_key
|
|
39
|
+
|
|
40
|
+
# AI model name to pass in the request body (e.g. "gpt-4o", "gpt-3.5-turbo").
|
|
41
|
+
# Optional — if nil, the API default or deployment model is used.
|
|
42
|
+
attr_accessor :ai_model
|
|
43
|
+
|
|
44
|
+
# AI auth style: :bearer (OpenAI, Ollama Cloud) or :api_key (Azure OpenAI).
|
|
45
|
+
# Defaults to :api_key for backwards compatibility.
|
|
46
|
+
attr_accessor :ai_auth_style
|
|
47
|
+
|
|
48
|
+
# Custom system prompt prepended to AI suggestions. Use this to describe
|
|
49
|
+
# your domain, table relationships, and naming conventions.
|
|
50
|
+
attr_accessor :ai_system_context
|
|
51
|
+
|
|
52
|
+
# Slow query threshold in milliseconds. Queries slower than this are logged.
|
|
53
|
+
attr_accessor :slow_query_threshold_ms
|
|
54
|
+
|
|
55
|
+
# Redis URL for slow query storage. Set to nil to disable slow query monitoring.
|
|
56
|
+
attr_accessor :redis_url
|
|
57
|
+
|
|
58
|
+
# Logger instance for audit logging. Defaults to a file logger.
|
|
59
|
+
# Set to nil to disable audit logging.
|
|
60
|
+
attr_accessor :audit_logger
|
|
61
|
+
|
|
62
|
+
# Base controller class for the engine to inherit from.
|
|
63
|
+
# Set to "ApplicationController" to get current_user and other app helpers.
|
|
64
|
+
# Defaults to "ActionController::Base".
|
|
65
|
+
attr_accessor :base_controller
|
|
66
|
+
|
|
67
|
+
def initialize
|
|
68
|
+
@featured_tables = []
|
|
69
|
+
@blocked_tables = %w[
|
|
70
|
+
sessions
|
|
71
|
+
ar_internal_metadata
|
|
72
|
+
schema_migrations
|
|
73
|
+
]
|
|
74
|
+
@masked_column_patterns = %w[password secret digest token]
|
|
75
|
+
@default_columns = {}
|
|
76
|
+
@max_row_limit = 1000
|
|
77
|
+
@default_row_limit = 25
|
|
78
|
+
@query_timeout_ms = 30_000
|
|
79
|
+
@authenticate = ->(controller) { true }
|
|
80
|
+
@ai_client = nil
|
|
81
|
+
@ai_endpoint = nil
|
|
82
|
+
@ai_api_key = nil
|
|
83
|
+
@ai_model = nil
|
|
84
|
+
@ai_auth_style = :api_key
|
|
85
|
+
@ai_system_context = nil
|
|
86
|
+
@slow_query_threshold_ms = 250
|
|
87
|
+
@redis_url = nil
|
|
88
|
+
@audit_logger = nil
|
|
89
|
+
@base_controller = "ActionController::Base"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def ai_enabled?
|
|
93
|
+
!ai_client.nil? || (!ai_endpoint.nil? && !ai_endpoint.empty? && !ai_api_key.nil? && !ai_api_key.empty?)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module MysqlGenius
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
isolate_namespace MysqlGenius
|
|
4
|
+
|
|
5
|
+
config.after_initialize do
|
|
6
|
+
if MysqlGenius.configuration.redis_url.present?
|
|
7
|
+
require "mysql_genius/slow_query_monitor"
|
|
8
|
+
MysqlGenius::SlowQueryMonitor.subscribe!
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
module MysqlGenius
|
|
4
|
+
class SlowQueryMonitor
|
|
5
|
+
def self.redis_key
|
|
6
|
+
"mysql_genius:slow_queries"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.subscribe!
|
|
10
|
+
ActiveSupport::Notifications.subscribe("sql.active_record") do |_name, start, finish, _id, payload|
|
|
11
|
+
duration_ms = ((finish - start) * 1000).round(1)
|
|
12
|
+
sql = payload[:sql].to_s
|
|
13
|
+
threshold = MysqlGenius.configuration.slow_query_threshold_ms
|
|
14
|
+
|
|
15
|
+
next unless duration_ms >= threshold
|
|
16
|
+
next unless sql.match?(/\ASELECT\b/i)
|
|
17
|
+
next if sql.include?("SCHEMA")
|
|
18
|
+
next if sql.include?("EXPLAIN")
|
|
19
|
+
next if payload[:name] == "SCHEMA"
|
|
20
|
+
|
|
21
|
+
begin
|
|
22
|
+
redis = Redis.new(url: MysqlGenius.configuration.redis_url)
|
|
23
|
+
entry = {
|
|
24
|
+
sql: sql.truncate(10_000),
|
|
25
|
+
duration_ms: duration_ms,
|
|
26
|
+
timestamp: Time.current.iso8601,
|
|
27
|
+
name: payload[:name]
|
|
28
|
+
}.to_json
|
|
29
|
+
|
|
30
|
+
redis.lpush(redis_key, entry)
|
|
31
|
+
redis.ltrim(redis_key, 0, 199)
|
|
32
|
+
rescue => e
|
|
33
|
+
Rails.logger.debug("[mysql_genius] Slow query logger error: #{e.message}") if defined?(Rails)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module MysqlGenius
|
|
2
|
+
module SqlValidator
|
|
3
|
+
FORBIDDEN_KEYWORDS = %w[INSERT UPDATE DELETE DROP ALTER CREATE TRUNCATE GRANT REVOKE].freeze
|
|
4
|
+
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def validate(sql, blocked_tables:, connection:)
|
|
8
|
+
return "Please enter a query." if sql.nil? || sql.strip.empty?
|
|
9
|
+
|
|
10
|
+
normalized = sql.gsub(/--.*$/, "").gsub(%r{/\*.*?\*/}m, "").strip
|
|
11
|
+
|
|
12
|
+
unless normalized.match?(/\ASELECT\b/i) || normalized.match?(/\AWITH\b/i)
|
|
13
|
+
return "Only SELECT queries are allowed."
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
return "Access to system schemas is not allowed." if normalized.match?(/\b(information_schema|mysql|performance_schema|sys)\b/i)
|
|
17
|
+
|
|
18
|
+
FORBIDDEN_KEYWORDS.each do |keyword|
|
|
19
|
+
return "#{keyword} statements are not allowed." if normalized.match?(/\b#{keyword}\b/i)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
tables_in_query = extract_table_references(normalized, connection)
|
|
23
|
+
blocked = tables_in_query & blocked_tables
|
|
24
|
+
if blocked.any?
|
|
25
|
+
return "Access denied for table(s): #{blocked.join(', ')}."
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def extract_table_references(sql, connection)
|
|
32
|
+
tables = []
|
|
33
|
+
sql.scan(/\bFROM\s+((?:`?\w+`?(?:\s*,\s*`?\w+`?)*)+)/i) { |m| m[0].scan(/`?(\w+)`?/) { |t| tables << t[0] } }
|
|
34
|
+
sql.scan(/\bJOIN\s+`?(\w+)`?/i) { |m| tables << m[0] }
|
|
35
|
+
sql.scan(/\b(?:INTO|UPDATE)\s+`?(\w+)`?/i) { |m| tables << m[0] }
|
|
36
|
+
tables.uniq.map(&:downcase) & connection.tables
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def apply_row_limit(sql, limit)
|
|
40
|
+
if sql.match?(/\bLIMIT\s+\d+\s*,\s*\d+/i)
|
|
41
|
+
sql.gsub(/\bLIMIT\s+(\d+)\s*,\s*(\d+)/i) do
|
|
42
|
+
"LIMIT #{::Regexp.last_match(1).to_i}, #{[::Regexp.last_match(2).to_i, limit].min}"
|
|
43
|
+
end
|
|
44
|
+
elsif sql.match?(/\bLIMIT\s+\d+/i)
|
|
45
|
+
sql.gsub(/\bLIMIT\s+(\d+)/i) { "LIMIT #{[::Regexp.last_match(1).to_i, limit].min}" }
|
|
46
|
+
else
|
|
47
|
+
"#{sql.gsub(/;\s*\z/, '')} LIMIT #{limit}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def masked_column?(column_name, patterns)
|
|
52
|
+
patterns.any? { |pattern| column_name.downcase.include?(pattern) }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/mysql_genius.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require "mysql_genius/version"
|
|
2
|
+
require "mysql_genius/configuration"
|
|
3
|
+
require "mysql_genius/sql_validator"
|
|
4
|
+
|
|
5
|
+
module MysqlGenius
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def configuration
|
|
10
|
+
@configuration ||= Configuration.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def configure
|
|
14
|
+
yield(configuration)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def reset_configuration!
|
|
18
|
+
@configuration = Configuration.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
require "mysql_genius/engine" if defined?(Rails)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require "mysql_genius/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "mysql_genius"
|
|
7
|
+
spec.version = MysqlGenius::VERSION
|
|
8
|
+
spec.authors = ["Antarr Byrd"]
|
|
9
|
+
spec.email = ["antarr.t.byrd@uth.tmc.edu"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "A MySQL performance dashboard and query explorer for Rails — like PgHero, but for MySQL."
|
|
12
|
+
spec.description = "MysqlGenius gives Rails apps a mountable admin dashboard for MySQL databases. " \
|
|
13
|
+
"Includes a safe SQL query explorer with visual builder, EXPLAIN analysis, " \
|
|
14
|
+
"slow query monitoring, audit logging, and optional AI-powered query suggestions and optimization."
|
|
15
|
+
spec.homepage = "https://github.com/antarr/mysql_genius"
|
|
16
|
+
spec.license = "MIT"
|
|
17
|
+
|
|
18
|
+
spec.required_ruby_version = ">= 2.6.0"
|
|
19
|
+
|
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
21
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
22
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
end
|
|
27
|
+
spec.bindir = "exe"
|
|
28
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
29
|
+
spec.require_paths = ["lib"]
|
|
30
|
+
|
|
31
|
+
spec.add_dependency "railties", ">= 5.2"
|
|
32
|
+
spec.add_dependency "activerecord", ">= 5.2"
|
|
33
|
+
|
|
34
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mysql_genius
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Antarr Byrd
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-04-09 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: railties
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.2'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '5.2'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: activerecord
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '5.2'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '5.2'
|
|
41
|
+
description: MysqlGenius gives Rails apps a mountable admin dashboard for MySQL databases.
|
|
42
|
+
Includes a safe SQL query explorer with visual builder, EXPLAIN analysis, slow query
|
|
43
|
+
monitoring, audit logging, and optional AI-powered query suggestions and optimization.
|
|
44
|
+
email:
|
|
45
|
+
- antarr.t.byrd@uth.tmc.edu
|
|
46
|
+
executables: []
|
|
47
|
+
extensions: []
|
|
48
|
+
extra_rdoc_files: []
|
|
49
|
+
files:
|
|
50
|
+
- ".github/workflows/ci.yml"
|
|
51
|
+
- ".gitignore"
|
|
52
|
+
- ".rspec"
|
|
53
|
+
- CHANGELOG.md
|
|
54
|
+
- Gemfile
|
|
55
|
+
- LICENSE.txt
|
|
56
|
+
- README.md
|
|
57
|
+
- Rakefile
|
|
58
|
+
- app/controllers/concerns/mysql_genius/ai_features.rb
|
|
59
|
+
- app/controllers/concerns/mysql_genius/database_analysis.rb
|
|
60
|
+
- app/controllers/concerns/mysql_genius/query_execution.rb
|
|
61
|
+
- app/controllers/mysql_genius/base_controller.rb
|
|
62
|
+
- app/controllers/mysql_genius/queries_controller.rb
|
|
63
|
+
- app/services/mysql_genius/ai_client.rb
|
|
64
|
+
- app/services/mysql_genius/ai_optimization_service.rb
|
|
65
|
+
- app/services/mysql_genius/ai_suggestion_service.rb
|
|
66
|
+
- app/views/layouts/mysql_genius/application.html.erb
|
|
67
|
+
- app/views/mysql_genius/queries/_shared_results.html.erb
|
|
68
|
+
- app/views/mysql_genius/queries/_tab_ai_tools.html.erb
|
|
69
|
+
- app/views/mysql_genius/queries/_tab_duplicate_indexes.html.erb
|
|
70
|
+
- app/views/mysql_genius/queries/_tab_query_stats.html.erb
|
|
71
|
+
- app/views/mysql_genius/queries/_tab_server.html.erb
|
|
72
|
+
- app/views/mysql_genius/queries/_tab_slow_queries.html.erb
|
|
73
|
+
- app/views/mysql_genius/queries/_tab_sql_query.html.erb
|
|
74
|
+
- app/views/mysql_genius/queries/_tab_table_sizes.html.erb
|
|
75
|
+
- app/views/mysql_genius/queries/_tab_unused_indexes.html.erb
|
|
76
|
+
- app/views/mysql_genius/queries/_tab_visual_builder.html.erb
|
|
77
|
+
- app/views/mysql_genius/queries/index.html.erb
|
|
78
|
+
- bin/console
|
|
79
|
+
- bin/setup
|
|
80
|
+
- config/routes.rb
|
|
81
|
+
- docs/screenshots/ai_tools.png
|
|
82
|
+
- docs/screenshots/duplicate_indexes.png
|
|
83
|
+
- docs/screenshots/query_stats.png
|
|
84
|
+
- docs/screenshots/server.png
|
|
85
|
+
- docs/screenshots/sql_query.png
|
|
86
|
+
- docs/screenshots/table_sizes.png
|
|
87
|
+
- docs/screenshots/visual_builder.png
|
|
88
|
+
- lib/mysql_genius.rb
|
|
89
|
+
- lib/mysql_genius/configuration.rb
|
|
90
|
+
- lib/mysql_genius/engine.rb
|
|
91
|
+
- lib/mysql_genius/slow_query_monitor.rb
|
|
92
|
+
- lib/mysql_genius/sql_validator.rb
|
|
93
|
+
- lib/mysql_genius/version.rb
|
|
94
|
+
- mysql_genius.gemspec
|
|
95
|
+
homepage: https://github.com/antarr/mysql_genius
|
|
96
|
+
licenses:
|
|
97
|
+
- MIT
|
|
98
|
+
metadata:
|
|
99
|
+
homepage_uri: https://github.com/antarr/mysql_genius
|
|
100
|
+
source_code_uri: https://github.com/antarr/mysql_genius
|
|
101
|
+
changelog_uri: https://github.com/antarr/mysql_genius/blob/main/CHANGELOG.md
|
|
102
|
+
post_install_message:
|
|
103
|
+
rdoc_options: []
|
|
104
|
+
require_paths:
|
|
105
|
+
- lib
|
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 2.6.0
|
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
|
+
requirements:
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: '0'
|
|
116
|
+
requirements: []
|
|
117
|
+
rubygems_version: 3.0.3.1
|
|
118
|
+
signing_key:
|
|
119
|
+
specification_version: 4
|
|
120
|
+
summary: A MySQL performance dashboard and query explorer for Rails — like PgHero,
|
|
121
|
+
but for MySQL.
|
|
122
|
+
test_files: []
|