pghero 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pghero might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8fe1e7db4a7b8d0181a485cf8239903d2d8bb8c3
4
- data.tar.gz: c2cda0f71c0e04d0fe345d86d114bbf49862b9c0
3
+ metadata.gz: 0c54bcd3e6419f74fe1bc9ad92ab5424ccde607d
4
+ data.tar.gz: a3a347148aad3b70bca436c805472a2dee80096f
5
5
  SHA512:
6
- metadata.gz: b0989fe3df1db33256d9cbc4affe14ea52ec44542827821deadc809eac6fe163d8aa48a6ec8573c9ea350644c235c9e7e57c2e085921e4db85ec6aae6290c8e7
7
- data.tar.gz: cd101a030b03c7b5adf8f73e88b850ab071f2c358564810a857995d877b3267014dafe226dd84b85b1f0e3a1b36bc6352b24912256e81e5c6ebe2b78a805273d
6
+ metadata.gz: a942b06fd72ba880d7c73b0bc3e35807d4a6f7c9ebe5b3df8ef2a8e131f8ab92871d1ca94b2c0eb35ca95cfe9d6d02efcc123741fecd66db9730dc70eafad3f0
7
+ data.tar.gz: d9727509fea173d2c698b2eddafd04834ef006f9c9463be61b0b9582bc555f0d894b34ee075dd8adc537489c575fc89257411f4083b3a690bc8ab47562a4e7f7
@@ -1,3 +1,8 @@
1
+ ## 1.4.0 [unreleased]
2
+
3
+ - Updated for Rails 5
4
+ - Fixed error when `pg_stat_statements` not enabled in `shared_libaries`
5
+
1
6
  ## 1.3.2
2
7
 
3
8
  - Improved performance of query stats
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in pghero.gemspec
4
4
  gemspec
5
+
6
+ gem "activerecord", "~> 5.0.0"
@@ -33,7 +33,10 @@ module PgHero
33
33
  @invalid_indexes = PgHero.invalid_indexes
34
34
  @duplicate_indexes = PgHero.duplicate_indexes if params[:duplicate_indexes]
35
35
  @good_cache_rate = @table_hit_rate >= PgHero.cache_hit_rate_threshold.to_f / 100 && @index_hit_rate >= PgHero.cache_hit_rate_threshold.to_f / 100
36
- @query_stats_available = PgHero.query_stats_available?
36
+ unless @query_stats_enabled
37
+ @query_stats_available = PgHero.query_stats_available?
38
+ @query_stats_extension_enabled = PgHero.query_stats_extension_enabled? if @query_stats_available
39
+ end
37
40
  @total_connections = PgHero.total_connections
38
41
  @good_total_connections = @total_connections < PgHero.total_connections_threshold
39
42
  if @replica
@@ -17,7 +17,8 @@
17
17
  <td><%= query["started_at"] ? "#{number_with_delimiter(((now - Time.parse(query["started_at"])) * 1000).round)} ms" : nil %></td>
18
18
  <td><%= query["source"] %> <span class="text-muted"><%= query["user"] %></span></td>
19
19
  <td class="text-right">
20
- <%= button_to "Explain", explain_path(query: query["query"]), form: {target: "_blank"}, class: "btn btn-info" %>
20
+ <% button_path, button_options = Rails.version >= "4.1" ? [explain_path, {params: {query: query["query"]}}] : [explain_path(query: query["query"]), {}] %>
21
+ <%= button_to "Explain", button_path, button_options.merge(form: {target: "_blank"}, class: "btn btn-info") %>
21
22
  <%= button_to "Kill", kill_path(pid: query["pid"]), class: "btn btn-danger" %>
22
23
  </td>
23
24
  </tr>
@@ -13,6 +13,6 @@ Row estimates
13
13
  <%= details[:row_estimates].to_a.map { |k, v| "- #{k}: #{v}" }.join("\n") %><% end %><% if details[:table_indexes] %>
14
14
 
15
15
  Existing indexes
16
- <% details[:table_indexes].sort_by { |i| [i["primary"] == "t" ? 0 : 1, i["columns"]] }.each do |i3| %>- <%= i3["columns"].join(", ") %><% if i3["using"] != "btree" %> <%= i3["using"].to_s.upcase %><% end %><% if i3["primary"] == "t" %> PRIMARY<% elsif i3["unique"] != "f" %> UNIQUE<% end %>
16
+ <% details[:table_indexes].sort_by { |i| [PgHero.truthy?(i["primary"]) ? 0 : 1, i["columns"]] }.each do |i3| %>- <%= i3["columns"].join(", ") %><% if i3["using"] != "btree" %> <%= i3["using"].to_s.upcase %><% end %><% if PgHero.truthy?(i3["primary"]) %> PRIMARY<% elsif PgHero.truthy?(i3["unique"]) %> UNIQUE<% end %>
17
17
  <% end %><% end %></pre></code>
18
18
  </div>
@@ -317,7 +317,7 @@ add_index <%= index[:table].to_sym.inspect %>, [<%= index[:columns].map(&:to_sym
317
317
  <div class="content">
318
318
  <h1>Query Stats</h1>
319
319
 
320
- <% if @query_stats_available %>
320
+ <% if @query_stats_available && !@query_stats_extension_enabled %>
321
321
  <p>
322
322
  Query stats are available but not enabled.
323
323
  <%= button_to "Enable", enable_query_stats_path, class: "btn btn-info" %>
@@ -45,12 +45,21 @@ module PgHero
45
45
  ssl_used = nil
46
46
  connection_model.transaction do
47
47
  execute("CREATE EXTENSION IF NOT EXISTS sslinfo")
48
- ssl_used = select_all("SELECT ssl_is_used()").first["ssl_is_used"] == "t"
48
+ ssl_used = truthy?(select_all("SELECT ssl_is_used()").first["ssl_is_used"])
49
49
  raise ActiveRecord::Rollback
50
50
  end
51
51
  ssl_used
52
52
  end
53
53
 
54
+ # Handles Rails 4 ('t') and Rails 5 (true) values.
55
+ def truthy?(value)
56
+ value == true || value == 't'
57
+ end
58
+
59
+ def falsey?(value)
60
+ value == false || value == 'f'
61
+ end
62
+
54
63
  private
55
64
 
56
65
  def friendly_value(setting, unit)
@@ -140,8 +140,8 @@ module PgHero
140
140
  indexes = []
141
141
 
142
142
  indexes_by_table = self.indexes.group_by { |i| i["table"] }
143
- indexes_by_table.values.flatten.select { |i| i["primary"] == "f" && i["unique"] == "f" && !i["indexprs"] && !i["indpred"] && i["valid"] == "t" }.each do |index|
144
- covering_index = indexes_by_table[index["table"]].find { |i| index_covers?(i["columns"], index["columns"]) && i["using"] == index["using"] && i["name"] != index["name"] && i["valid"] == "t" }
143
+ indexes_by_table.values.flatten.select { |i| falsey?(i["primary"]) && falsey?(i["unique"]) && !i["indexprs"] && !i["indpred"] && truthy?(i["valid"]) }.each do |index|
144
+ covering_index = indexes_by_table[index["table"]].find { |i| index_covers?(i["columns"], index["columns"]) && i["using"] == index["using"] && i["name"] != index["name"] && truthy?(i["valid"]) }
145
145
  if covering_index
146
146
  indexes << {"unneeded_index" => index, "covering_index" => covering_index}
147
147
  end
@@ -2,7 +2,7 @@ module PgHero
2
2
  module Methods
3
3
  module Kill
4
4
  def kill(pid)
5
- execute("SELECT pg_terminate_backend(#{pid.to_i})").first["pg_terminate_backend"] == "t"
5
+ truthy? execute("SELECT pg_terminate_backend(#{pid.to_i})").first["pg_terminate_backend"]
6
6
  end
7
7
 
8
8
  def kill_long_running_queries
@@ -31,11 +31,16 @@ module PgHero
31
31
  end
32
32
 
33
33
  def query_stats_enabled?
34
- select_all("SELECT COUNT(*) AS count FROM pg_extension WHERE extname = 'pg_stat_statements'").first["count"].to_i > 0 && query_stats_readable?
34
+ query_stats_extension_enabled? && query_stats_readable?
35
+ end
36
+
37
+ def query_stats_extension_enabled?
38
+ select_all("SELECT COUNT(*) AS count FROM pg_extension WHERE extname = 'pg_stat_statements'").first["count"].to_i > 0
35
39
  end
36
40
 
37
41
  def query_stats_readable?
38
- select_all("SELECT has_table_privilege(current_user, 'pg_stat_statements', 'SELECT')").first["has_table_privilege"] == "t"
42
+ select_all("SELECT * FROM pg_stat_statements LIMIT 1")
43
+ true
39
44
  rescue ActiveRecord::StatementInvalid
40
45
  false
41
46
  end
@@ -116,7 +121,7 @@ module PgHero
116
121
  # http://stackoverflow.com/questions/20582500/how-to-check-if-a-table-exists-in-a-given-schema
117
122
  def historical_query_stats_enabled?
118
123
  # TODO use schema from config
119
- stats_connection.select_all(squish <<-SQL
124
+ truthy? stats_connection.select_all(squish <<-SQL
120
125
  SELECT EXISTS (
121
126
  SELECT
122
127
  1
@@ -130,7 +135,7 @@ module PgHero
130
135
  AND c.relkind = 'r'
131
136
  )
132
137
  SQL
133
- ).to_a.first["exists"] == "t"
138
+ ).to_a.first["exists"]
134
139
  end
135
140
 
136
141
  def stats_connection
@@ -1,3 +1,3 @@
1
1
  module PgHero
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in pghero.gemspec
4
+ gemspec path: "../.."
5
+
6
+ gem "activerecord", "~> 4.2.0"
@@ -2,14 +2,19 @@ require_relative "test_helper"
2
2
 
3
3
  class SuggestedIndexesTest < Minitest::Test
4
4
  def setup
5
+ # no pg_stat_statements
6
+ skip if ENV["TRAVIS_CI"]
7
+
5
8
  PgHero.reset_query_stats
6
9
  end
7
10
 
8
11
  def test_basic
9
- # no pg_stat_statements
10
- skip if ENV["TRAVIS_CI"]
11
-
12
12
  User.where(email: "person1@example.org").first
13
13
  assert_equal [{table: "users", columns: ["email"]}], PgHero.suggested_indexes.map { |q| q.except(:queries, :details) }
14
14
  end
15
+
16
+ def test_existing_index
17
+ User.where("updated_at > ?", Time.now).to_a
18
+ assert_equal [], PgHero.suggested_indexes.map { |q| q.except(:queries, :details) }
19
+ end
15
20
  end
@@ -31,7 +31,9 @@ unless ENV["SKIP_SEED"]
31
31
  t.string :zip_code
32
32
  t.boolean :active
33
33
  t.timestamp :created_at
34
+ t.timestamp :updated_at
34
35
  end
36
+ ActiveRecord::Migration.add_index :users, :updated_at
35
37
 
36
38
  User.transaction do
37
39
  users =
@@ -43,7 +45,8 @@ unless ENV["SKIP_SEED"]
43
45
  login_attempts: rand(30),
44
46
  zip_code: i % 40 == 0 ? nil : "12345",
45
47
  active: true,
46
- created_at: Time.now - rand(50).days
48
+ created_at: Time.now - rand(50).days,
49
+ updated_at: Time.now - rand(50).days
47
50
  )
48
51
  end
49
52
  User.import users, validate: false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pghero
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-04 00:00:00.000000000 Z
11
+ date: 2016-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -175,6 +175,7 @@ files:
175
175
  - test/best_index_test.rb
176
176
  - test/explain_test.rb
177
177
  - test/gemfiles/activerecord41.gemfile
178
+ - test/gemfiles/activerecord42.gemfile
178
179
  - test/suggested_indexes_test.rb
179
180
  - test/test_helper.rb
180
181
  homepage: https://github.com/ankane/pghero
@@ -211,6 +212,7 @@ test_files:
211
212
  - test/best_index_test.rb
212
213
  - test/explain_test.rb
213
214
  - test/gemfiles/activerecord41.gemfile
215
+ - test/gemfiles/activerecord42.gemfile
214
216
  - test/suggested_indexes_test.rb
215
217
  - test/test_helper.rb
216
218
  has_rdoc: