rails-pg-extras 5.3.1 → 5.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +34 -32
- data/Gemfile +1 -1
- data/README.md +6 -2
- data/Rakefile +3 -4
- data/app/controllers/rails_pg_extras/web/application_controller.rb +4 -4
- data/app/controllers/rails_pg_extras/web/queries_controller.rb +1 -1
- data/app/views/rails_pg_extras/web/queries/_diagnose.html.erb +1 -1
- data/app/views/rails_pg_extras/web/queries/_unavailable_extensions_warning.html.erb +9 -9
- data/app/views/rails_pg_extras/web/queries/index.html.erb +10 -12
- data/app/views/rails_pg_extras/web/queries/show.html.erb +12 -13
- data/app/views/rails_pg_extras/web/shared/_queries_selector.html.erb +4 -5
- data/config/routes.rb +3 -3
- data/docker-compose.yml.sample +27 -10
- data/lib/rails-pg-extras.rb +27 -25
- data/lib/rails_pg_extras/diagnose_data.rb +0 -1
- data/lib/rails_pg_extras/diagnose_print.rb +0 -1
- data/lib/rails_pg_extras/railtie.rb +1 -1
- data/lib/rails_pg_extras/tasks/all.rake +1 -1
- data/lib/rails_pg_extras/version.rb +1 -1
- data/lib/rails_pg_extras/web/engine.rb +1 -1
- data/rails-pg-extras.gemspec +13 -12
- data/spec/smoke_spec.rb +6 -5
- data/spec/spec_helper.rb +19 -15
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eae7b49e84af570a46a1442642dcc8a1f9abc78d660489d777715b7fde100224
|
4
|
+
data.tar.gz: 4fd17ae15d5dc2b0eddfd8f4770dfe062efeee119d1d797f4ffb00c4e8e369f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0f610b3eea483eaf8a7d2e321a0af7a805633d70e1e473905d0aae5993f5dc70055a39cee07634f3e7dc1691cd70c77d9b25440018e0b6550645378b65aadf8
|
7
|
+
data.tar.gz: e506327e15ee0d8072f74b712abb4552c0dfe34b8f6dfd53149dbd439bf4bba96064d1c61bf5dfae979a46571fb9dd776382893890740648ae8bb624a932aa9c
|
data/.github/workflows/ci.yml
CHANGED
@@ -12,43 +12,52 @@ jobs:
|
|
12
12
|
strategy:
|
13
13
|
fail-fast: false
|
14
14
|
matrix:
|
15
|
-
ruby-version: ['3.2', '3.1', '3.0', '2.7', '2.6']
|
15
|
+
ruby-version: ['3.3', '3.2', '3.1', '3.0', '2.7', '2.6']
|
16
16
|
steps:
|
17
|
-
- uses: actions/checkout@
|
18
|
-
- name: Run PostgreSQL
|
17
|
+
- uses: actions/checkout@v4
|
18
|
+
- name: Run PostgreSQL 12
|
19
19
|
run: |
|
20
20
|
docker run --env POSTGRES_USER=postgres \
|
21
21
|
--env POSTGRES_DB=rails-pg-extras-test \
|
22
22
|
--env POSTGRES_PASSWORD=secret \
|
23
|
-
-d -p 5432:5432 postgres:
|
23
|
+
-d -p 5432:5432 postgres:12.20-alpine \
|
24
24
|
postgres -c shared_preload_libraries=pg_stat_statements
|
25
|
-
- name: Run PostgreSQL
|
25
|
+
- name: Run PostgreSQL 13
|
26
26
|
run: |
|
27
27
|
docker run --env POSTGRES_USER=postgres \
|
28
28
|
--env POSTGRES_DB=rails-pg-extras-test \
|
29
29
|
--env POSTGRES_PASSWORD=secret \
|
30
|
-
-d -p 5433:5432 postgres:
|
30
|
+
-d -p 5433:5432 postgres:13.16-alpine \
|
31
31
|
postgres -c shared_preload_libraries=pg_stat_statements
|
32
|
-
- name: Run PostgreSQL
|
32
|
+
- name: Run PostgreSQL 14
|
33
33
|
run: |
|
34
34
|
docker run --env POSTGRES_USER=postgres \
|
35
35
|
--env POSTGRES_DB=rails-pg-extras-test \
|
36
36
|
--env POSTGRES_PASSWORD=secret \
|
37
|
-
-d -p 5434:5432 postgres:13
|
37
|
+
-d -p 5434:5432 postgres:14.13-alpine \
|
38
38
|
postgres -c shared_preload_libraries=pg_stat_statements
|
39
|
-
- name: Run PostgreSQL
|
39
|
+
- name: Run PostgreSQL 15
|
40
40
|
run: |
|
41
41
|
docker run --env POSTGRES_USER=postgres \
|
42
42
|
--env POSTGRES_DB=rails-pg-extras-test \
|
43
43
|
--env POSTGRES_PASSWORD=secret \
|
44
|
-
-d -p 5435:5432 postgres:
|
44
|
+
-d -p 5435:5432 postgres:15.8-alpine \
|
45
45
|
postgres -c shared_preload_libraries=pg_stat_statements
|
46
|
-
|
46
|
+
sleep 15
|
47
|
+
- name: Run PostgreSQL 16
|
48
|
+
run: |
|
49
|
+
docker run --env POSTGRES_USER=postgres \
|
50
|
+
--env POSTGRES_DB=rails-pg-extras-test \
|
51
|
+
--env POSTGRES_PASSWORD=secret \
|
52
|
+
-d -p 5436:5432 postgres:16.4-alpine \
|
53
|
+
postgres -c shared_preload_libraries=pg_stat_statements
|
54
|
+
sleep 15
|
55
|
+
- name: Run PostgreSQL 17
|
47
56
|
run: |
|
48
57
|
docker run --env POSTGRES_USER=postgres \
|
49
58
|
--env POSTGRES_DB=rails-pg-extras-test \
|
50
59
|
--env POSTGRES_PASSWORD=secret \
|
51
|
-
-d -p
|
60
|
+
-d -p 5437:5432 postgres:17.0-alpine \
|
52
61
|
postgres -c shared_preload_libraries=pg_stat_statements
|
53
62
|
sleep 15
|
54
63
|
- name: Set up Ruby ${{ matrix.ruby-version }}
|
@@ -57,72 +66,65 @@ jobs:
|
|
57
66
|
ruby-version: ${{ matrix.ruby-version }}
|
58
67
|
- name: Setup dependencies
|
59
68
|
run: |
|
60
|
-
gem
|
61
|
-
gem install bundler
|
69
|
+
gem install bundler -v 2.4.22
|
62
70
|
sudo apt-get update --allow-releaseinfo-change
|
63
71
|
sudo apt install postgresql-client
|
64
72
|
sudo apt install libpq-dev
|
65
73
|
bundle config set --local path 'vendor/bundle'
|
66
74
|
bundle install
|
67
75
|
sleep 10
|
68
|
-
- name: Run tests for PG
|
76
|
+
- name: Run tests for PG 12
|
69
77
|
env:
|
70
|
-
PG_VERSION:
|
78
|
+
PG_VERSION: 12
|
71
79
|
POSTGRES_HOST: localhost
|
72
80
|
POSTGRES_USER: postgres
|
73
81
|
POSTGRES_DB: rails-pg-extras-test
|
74
82
|
POSTGRES_PASSWORD: secret
|
75
|
-
DATABASE_URL: postgresql://postgres:secret@localhost:5432/rails-pg-extras-test
|
76
83
|
run: |
|
77
84
|
bundle exec rspec spec/
|
78
|
-
- name: Run tests for PG
|
85
|
+
- name: Run tests for PG 13
|
79
86
|
env:
|
80
|
-
PG_VERSION:
|
87
|
+
PG_VERSION: 13
|
81
88
|
POSTGRES_HOST: localhost
|
82
89
|
POSTGRES_USER: postgres
|
83
90
|
POSTGRES_DB: rails-pg-extras-test
|
84
91
|
POSTGRES_PASSWORD: secret
|
85
|
-
DATABASE_URL: postgresql://postgres:secret@localhost:5432/rails-pg-extras-test
|
86
92
|
run: |
|
87
93
|
bundle exec rspec spec/
|
88
|
-
- name: Run tests for PG
|
94
|
+
- name: Run tests for PG 14
|
89
95
|
env:
|
90
|
-
PG_VERSION:
|
96
|
+
PG_VERSION: 14
|
91
97
|
POSTGRES_HOST: localhost
|
92
98
|
POSTGRES_USER: postgres
|
93
99
|
POSTGRES_DB: rails-pg-extras-test
|
94
100
|
POSTGRES_PASSWORD: secret
|
95
|
-
DATABASE_URL: postgresql://postgres:secret@localhost:5433/rails-pg-extras-test
|
96
101
|
run: |
|
97
102
|
bundle exec rspec spec/
|
98
|
-
- name: Run tests for PG
|
103
|
+
- name: Run tests for PG 15
|
99
104
|
env:
|
100
|
-
PG_VERSION:
|
105
|
+
PG_VERSION: 15
|
101
106
|
POSTGRES_HOST: localhost
|
102
107
|
POSTGRES_USER: postgres
|
103
108
|
POSTGRES_DB: rails-pg-extras-test
|
104
109
|
POSTGRES_PASSWORD: secret
|
105
|
-
DATABASE_URL: postgresql://postgres:secret@localhost:5434/rails-pg-extras-test
|
106
110
|
run: |
|
107
111
|
bundle exec rspec spec/
|
108
|
-
- name: Run tests for PG
|
112
|
+
- name: Run tests for PG 16
|
109
113
|
env:
|
110
|
-
PG_VERSION:
|
114
|
+
PG_VERSION: 16
|
111
115
|
POSTGRES_HOST: localhost
|
112
116
|
POSTGRES_USER: postgres
|
113
117
|
POSTGRES_DB: rails-pg-extras-test
|
114
118
|
POSTGRES_PASSWORD: secret
|
115
|
-
DATABASE_URL: postgresql://postgres:secret@localhost:5435/rails-pg-extras-test
|
116
119
|
run: |
|
117
120
|
bundle exec rspec spec/
|
118
|
-
- name: Run tests for PG
|
121
|
+
- name: Run tests for PG 17
|
119
122
|
env:
|
120
|
-
PG_VERSION:
|
123
|
+
PG_VERSION: 17
|
121
124
|
POSTGRES_HOST: localhost
|
122
125
|
POSTGRES_USER: postgres
|
123
126
|
POSTGRES_DB: rails-pg-extras-test
|
124
127
|
POSTGRES_PASSWORD: secret
|
125
|
-
DATABASE_URL: postgresql://postgres:secret@localhost:5436/rails-pg-extras-test
|
126
128
|
run: |
|
127
129
|
bundle exec rspec spec/
|
128
130
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ Included rake tasks and Ruby methods can be used to obtain information about a P
|
|
6
6
|
|
7
7
|
You can read this blog post for detailed step by step tutorial on how to [optimize PostgreSQL using PG Extras library](https://pawelurbanek.com/postgresql-fix-performance).
|
8
8
|
|
9
|
-
**Shameless plug:** rails-pg-extras is one of the tools that I use when conducting Rails performance audits
|
9
|
+
**Shameless plug:** rails-pg-extras is just one of the tools that I use when conducting [Rails performance audits](https://pawelurbanek.com/optimize-rails-performance). Check out my offer if you need help with optimizing your application.
|
10
10
|
|
11
11
|
Optionally you can enable a visual interface:
|
12
12
|
|
@@ -16,6 +16,8 @@ Alternative versions:
|
|
16
16
|
|
17
17
|
- Core dependency - [Ruby](https://github.com/pawurb/ruby-pg-extras)
|
18
18
|
|
19
|
+
- [Rust](https://github.com/pawurb/rust-pg-extras)
|
20
|
+
|
19
21
|
- [NodeJS](https://github.com/pawurb/node-postgres-extras)
|
20
22
|
|
21
23
|
- [Elixir](https://github.com/pawurb/ecto_psql_extras)
|
@@ -109,6 +111,8 @@ By default, queries target the `public` schema of the database. You can specify
|
|
109
111
|
RailsPgExtras.table_cache_hit(args: { schema: "my_schema" })
|
110
112
|
```
|
111
113
|
|
114
|
+
You can customize the default `public` schema by setting `ENV['PG_EXTRAS_SCHEMA']` value.
|
115
|
+
|
112
116
|
## Diagnose report
|
113
117
|
|
114
118
|
The simplest way to start using pg-extras is to execute a `diagnose` method. It runs a set of checks and prints out a report highlighting areas that may require additional investigation:
|
@@ -544,7 +548,7 @@ This command displays the total size of each table and materialized view in the
|
|
544
548
|
### `unused_indexes`
|
545
549
|
|
546
550
|
```ruby
|
547
|
-
RailsPgExtras.unused_indexes(args: { max_scans:
|
551
|
+
RailsPgExtras.unused_indexes(args: { max_scans: 50 })
|
548
552
|
|
549
553
|
$ rake pg_extras:unused_indexes
|
550
554
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require
|
2
|
+
require "rspec/core/rake_task"
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
-
desc
|
6
|
+
desc "Test all PG versions"
|
7
7
|
task :test_all do
|
8
|
-
system("PG_VERSION=
|
8
|
+
system("PG_VERSION=12 bundle exec rspec spec/ && PG_VERSION=13 bundle exec rspec spec/ && PG_VERSION=14 bundle exec rspec spec/ && PG_VERSION=15 bundle exec rspec spec/ && PG_VERSION=16 bundle exec rspec spec/ && PG_VERSION=17 bundle exec rspec spec/")
|
9
9
|
end
|
10
|
-
|
@@ -9,17 +9,17 @@ module RailsPgExtras::Web
|
|
9
9
|
REQUIRED_EXTENSIONS = {
|
10
10
|
pg_stat_statements: %i[calls outliers pg_stat_statements_reset],
|
11
11
|
pg_buffercache: %i[buffercache_stats buffercache_usage],
|
12
|
-
sslinfo: %i[ssl_used]
|
12
|
+
sslinfo: %i[ssl_used],
|
13
13
|
}
|
14
14
|
|
15
15
|
ACTIONS = %i[kill_all pg_stat_statements_reset add_extensions]
|
16
16
|
|
17
|
-
if ENV[
|
18
|
-
http_basic_authenticate_with name: ENV.fetch(
|
17
|
+
if ENV["RAILS_PG_EXTRAS_USER"].present? && ENV["RAILS_PG_EXTRAS_PASSWORD"].present?
|
18
|
+
http_basic_authenticate_with name: ENV.fetch("RAILS_PG_EXTRAS_USER"), password: ENV.fetch("RAILS_PG_EXTRAS_PASSWORD")
|
19
19
|
end
|
20
20
|
|
21
21
|
def validate_credentials!
|
22
|
-
if (ENV[
|
22
|
+
if (ENV["RAILS_PG_EXTRAS_USER"].blank? || ENV["RAILS_PG_EXTRAS_PASSWORD"].blank?) && !RailsPgExtras.configuration.public_dashboard
|
23
23
|
raise "Missing credentials for rails-pg-extras dashboard! If you want to enable public dashboard please set RAILS_PG_EXTRAS_PUBLIC_DASHBOARD=true"
|
24
24
|
end
|
25
25
|
end
|
@@ -38,7 +38,7 @@ module RailsPgExtras::Web
|
|
38
38
|
return @unavailable_extensions if defined?(@unavailable_extensions)
|
39
39
|
|
40
40
|
enabled_extensions = ActiveRecord::Base.connection.extensions
|
41
|
-
@unavailable_extensions = REQUIRED_EXTENSIONS.delete_if { |ext| ext.to_s.in?(enabled_extensions)
|
41
|
+
@unavailable_extensions = REQUIRED_EXTENSIONS.delete_if { |ext| ext.to_s.in?(enabled_extensions) }
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<h1 class="font-bold text-xl my-5">Diagnose</h1>
|
2
2
|
<table class="w-full font-mono border-collapse border my-5">
|
3
3
|
<% RailsPgExtras.diagnose(in_format: :hash).each do |diagnosis| %>
|
4
|
-
<tr class="<%= diagnosis[:ok] ?
|
4
|
+
<tr class="<%= diagnosis[:ok] ? "bg-green-300" : "bg-red-300" %>">
|
5
5
|
<td class='p-1 border font-bold'><%= diagnosis[:check_name] %></td>
|
6
6
|
<td class='p-1 border'><%= diagnosis[:message] %></td>
|
7
7
|
</tr>
|
@@ -1,15 +1,15 @@
|
|
1
1
|
<div class="text-red-500 p-3 font-mono my-5">
|
2
|
-
<% unavailable_extensions.each do |extension, queries| %>
|
2
|
+
<% unavailable_extensions.each do |extension, queries| %>
|
3
3
|
WARNING: Queries <%= queries.map { |q| "<b><u>#{q}</u></b>" }.join(", ").html_safe %> require extension: <b><%= extension %></b>
|
4
4
|
<br>
|
5
|
-
<% end %>
|
5
|
+
<% end %>
|
6
6
|
</div>
|
7
7
|
|
8
|
-
<% if RailsPgExtras::Web.action_enabled?(:add_extensions) %>
|
9
|
-
<%= link_to "Enable extensions", add_extensions_action_path,
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
<% end %>
|
8
|
+
<% if RailsPgExtras::Web.action_enabled?(:add_extensions) %>
|
9
|
+
<%= link_to "Enable extensions", add_extensions_action_path,
|
10
|
+
method: "post",
|
11
|
+
data: {
|
12
|
+
confirm: "This command will enable following extensions: #{unavailable_extensions.keys.join(", ")}. Do you want to proceeed?",
|
13
|
+
}, class: "border p-3 bg-green-500 text-white hover:bg-green-600 font-bold rounded" %>
|
14
|
+
<% end %>
|
15
15
|
|
@@ -6,20 +6,18 @@
|
|
6
6
|
<h1 class="font-bold text-xl my-5">Actions</h1>
|
7
7
|
|
8
8
|
<% if RailsPgExtras::Web.action_enabled?(:kill_all) %>
|
9
|
-
<%= link_to "kill_all",
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
%>
|
9
|
+
<%= link_to "kill_all", kill_all_action_path,
|
10
|
+
method: "post",
|
11
|
+
data: {
|
12
|
+
confirm: "This commands kills all the currently active connections to the database. Do you want to proceed?",
|
13
|
+
},
|
14
|
+
class: "border p-3 bg-red-500 text-white hover:bg-red-600 font-bold rounded" %>
|
16
15
|
<% end %>
|
17
16
|
|
18
17
|
<% if RailsPgExtras::Web.action_enabled?(:pg_stat_statements_reset) && unavailable_extensions.exclude?(:pg_stat_statements) %>
|
19
18
|
<%= link_to "pg_stat_statements_reset", pg_stat_statements_reset_action_path,
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
%>
|
19
|
+
method: "post",
|
20
|
+
data: {
|
21
|
+
confirm: "This command discards all statistics gathered so far by pg_stat_statements. Do you want to proceed?",
|
22
|
+
}, class: "border p-3 bg-blue-500 text-white hover:bg-blue-600 font-bold rounded" %>
|
25
23
|
<% end %>
|
@@ -1,19 +1,18 @@
|
|
1
|
-
<%= content_for :title, params[:query_name].presence || "pg_extras" %>
|
2
|
-
<%= render "rails_pg_extras/web/shared/queries_selector" %>
|
1
|
+
<%= content_for :title, params[:query_name].presence || "pg_extras" %>
|
2
|
+
<%= render "rails_pg_extras/web/shared/queries_selector" %>
|
3
3
|
|
4
|
-
<% if @error %>
|
4
|
+
<% if @error %>
|
5
5
|
<div class="text-red-500 p-3 font-mono my-5"><%= @error %></div>
|
6
|
-
<% else %>
|
7
|
-
<% if @result&.any? %>
|
8
|
-
<%= render "result",
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
<% else %>
|
6
|
+
<% else %>
|
7
|
+
<% if @result&.any? %>
|
8
|
+
<%= render "result",
|
9
|
+
title: RubyPgExtras.description_for(query_name: @query_name),
|
10
|
+
headers: @result[0].keys,
|
11
|
+
rows: @result.values %>
|
12
|
+
<% else %>
|
14
13
|
<div class="font-mono p-3 bg-gray-100 mt-3">No results</div>
|
15
|
-
<% end %>
|
16
|
-
<% end %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
17
16
|
|
18
17
|
<style>
|
19
18
|
@media print {
|
@@ -1,8 +1,7 @@
|
|
1
|
-
<%= form_tag queries_path, id: "queries", method: :get do |f| %>
|
2
|
-
<%= select_tag :query_name, options_for_select(@all_queries, params[:query_name]),
|
3
|
-
|
4
|
-
|
5
|
-
<% end %>
|
1
|
+
<%= form_tag queries_path, id: "queries", method: :get do |f| %>
|
2
|
+
<%= select_tag :query_name, options_for_select(@all_queries, params[:query_name]),
|
3
|
+
{ prompt: "--- select query ---", class: "border p-2 font-bold", autofocus: true } %>
|
4
|
+
<% end %>
|
6
5
|
|
7
6
|
<%= javascript_tag nonce: true do -%>
|
8
7
|
document.getElementById('queries').addEventListener('change', (e) => {
|
data/config/routes.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
RailsPgExtras::Web::Engine.routes.draw do
|
2
2
|
resources :queries, only: [:index]
|
3
3
|
|
4
|
-
post "/actions/kill_all"
|
5
|
-
post "/actions/pg_stat_statements_reset"
|
6
|
-
post "/actions/add_extensions"
|
4
|
+
post "/actions/kill_all", to: "actions#kill_all", as: :kill_all_action
|
5
|
+
post "/actions/pg_stat_statements_reset", to: "actions#pg_stat_statements_reset", as: :pg_stat_statements_reset_action
|
6
|
+
post "/actions/add_extensions", to: "actions#add_extensions", as: :add_extensions_action
|
7
7
|
|
8
8
|
root to: "queries#index"
|
9
9
|
end
|
data/docker-compose.yml.sample
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
version: '3'
|
2
|
-
|
3
1
|
services:
|
4
|
-
|
5
|
-
image: postgres:
|
2
|
+
postgres12:
|
3
|
+
image: postgres:12.20-alpine
|
6
4
|
command: postgres -c shared_preload_libraries=pg_stat_statements
|
7
5
|
environment:
|
8
6
|
POSTGRES_USER: postgres
|
@@ -10,8 +8,8 @@ services:
|
|
10
8
|
POSTGRES_PASSWORD: secret
|
11
9
|
ports:
|
12
10
|
- '5432:5432'
|
13
|
-
|
14
|
-
image: postgres:
|
11
|
+
postgres13:
|
12
|
+
image: postgres:13.16-alpine
|
15
13
|
command: postgres -c shared_preload_libraries=pg_stat_statements
|
16
14
|
environment:
|
17
15
|
POSTGRES_USER: postgres
|
@@ -19,8 +17,8 @@ services:
|
|
19
17
|
POSTGRES_PASSWORD: secret
|
20
18
|
ports:
|
21
19
|
- '5433:5432'
|
22
|
-
|
23
|
-
image: postgres:13
|
20
|
+
postgres14:
|
21
|
+
image: postgres:14.13-alpine
|
24
22
|
command: postgres -c shared_preload_libraries=pg_stat_statements
|
25
23
|
environment:
|
26
24
|
POSTGRES_USER: postgres
|
@@ -28,8 +26,8 @@ services:
|
|
28
26
|
POSTGRES_PASSWORD: secret
|
29
27
|
ports:
|
30
28
|
- '5434:5432'
|
31
|
-
|
32
|
-
image: postgres:
|
29
|
+
postgres15:
|
30
|
+
image: postgres:15.8-alpine
|
33
31
|
command: postgres -c shared_preload_libraries=pg_stat_statements
|
34
32
|
environment:
|
35
33
|
POSTGRES_USER: postgres
|
@@ -37,3 +35,22 @@ services:
|
|
37
35
|
POSTGRES_PASSWORD: secret
|
38
36
|
ports:
|
39
37
|
- '5435:5432'
|
38
|
+
postgres16:
|
39
|
+
image: postgres:16.4-alpine
|
40
|
+
command: postgres -c shared_preload_libraries=pg_stat_statements
|
41
|
+
environment:
|
42
|
+
POSTGRES_USER: postgres
|
43
|
+
POSTGRES_DB: rails-pg-extras-test
|
44
|
+
POSTGRES_PASSWORD: secret
|
45
|
+
ports:
|
46
|
+
- '5436:5432'
|
47
|
+
postgres17:
|
48
|
+
image: postgres:17.0-alpine
|
49
|
+
command: postgres -c shared_preload_libraries=pg_stat_statements
|
50
|
+
environment:
|
51
|
+
POSTGRES_USER: postgres
|
52
|
+
POSTGRES_DB: rails-pg-extras-test
|
53
|
+
POSTGRES_PASSWORD: secret
|
54
|
+
ports:
|
55
|
+
- '5437:5432'
|
56
|
+
|
data/lib/rails-pg-extras.rb
CHANGED
@@ -1,25 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
3
|
+
require "terminal-table"
|
4
|
+
require "ruby-pg-extras"
|
5
|
+
require "rails_pg_extras/diagnose_data"
|
6
|
+
require "rails_pg_extras/diagnose_print"
|
7
|
+
require "rails_pg_extras/index_info"
|
8
|
+
require "rails_pg_extras/index_info_print"
|
9
|
+
require "rails_pg_extras/table_info"
|
10
|
+
require "rails_pg_extras/table_info_print"
|
11
11
|
|
12
12
|
module RailsPgExtras
|
13
13
|
QUERIES = RubyPgExtras::QUERIES
|
14
14
|
DEFAULT_ARGS = RubyPgExtras::DEFAULT_ARGS
|
15
15
|
NEW_PG_STAT_STATEMENTS = RubyPgExtras::NEW_PG_STAT_STATEMENTS
|
16
|
+
PG_STAT_STATEMENTS_17 = RubyPgExtras::PG_STAT_STATEMENTS_17
|
16
17
|
|
17
18
|
QUERIES.each do |query_name|
|
18
19
|
define_singleton_method query_name do |options = {}|
|
19
20
|
run_query(
|
20
21
|
query_name: query_name,
|
21
22
|
in_format: options.fetch(:in_format, :display_table),
|
22
|
-
args: options.fetch(:args, {})
|
23
|
+
args: options.fetch(:args, {}),
|
23
24
|
)
|
24
25
|
end
|
25
26
|
end
|
@@ -30,25 +31,27 @@ module RailsPgExtras
|
|
30
31
|
FROM pg_available_extensions
|
31
32
|
WHERE name = 'pg_stat_statements'"
|
32
33
|
if (version = RailsPgExtras.connection.execute(pg_stat_statements_version_sql)
|
33
|
-
|
34
|
+
.to_a[0].fetch("installed_version", nil))
|
34
35
|
if Gem::Version.new(version) < Gem::Version.new(NEW_PG_STAT_STATEMENTS)
|
35
36
|
query_name = "#{query_name}_legacy".to_sym
|
37
|
+
elsif Gem::Version.new(version) >= Gem::Version.new(PG_STAT_STATEMENTS_17)
|
38
|
+
query_name = "#{query_name}_17".to_sym
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
40
43
|
sql = if (custom_args = DEFAULT_ARGS[query_name].merge(args)) != {}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
RubyPgExtras.sql_for(query_name: query_name) % custom_args
|
45
|
+
else
|
46
|
+
RubyPgExtras.sql_for(query_name: query_name)
|
47
|
+
end
|
45
48
|
|
46
49
|
result = connection.execute(sql)
|
47
50
|
|
48
51
|
RubyPgExtras.display_result(
|
49
52
|
result,
|
50
53
|
title: RubyPgExtras.description_for(query_name: query_name),
|
51
|
-
in_format: in_format
|
54
|
+
in_format: in_format,
|
52
55
|
)
|
53
56
|
end
|
54
57
|
|
@@ -76,10 +79,10 @@ module RailsPgExtras
|
|
76
79
|
sql_duration = 0
|
77
80
|
|
78
81
|
method_name = if ActiveSupport::Notifications.respond_to?(:monotonic_subscribe)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
82
|
+
:monotonic_subscribe
|
83
|
+
else
|
84
|
+
:subscribe
|
85
|
+
end
|
83
86
|
|
84
87
|
subscriber = ActiveSupport::Notifications.public_send(method_name, "sql.active_record") do |_name, start, finish, _id, payload|
|
85
88
|
unless payload[:name] =~ /SCHEMA/
|
@@ -115,11 +118,10 @@ module RailsPgExtras
|
|
115
118
|
count: queries.reduce(0) { |agg, val| agg + val[1].fetch(:count) },
|
116
119
|
queries: queries,
|
117
120
|
total_duration: total_duration.round(2),
|
118
|
-
sql_duration: sql_duration.round(2)
|
121
|
+
sql_duration: sql_duration.round(2),
|
119
122
|
}
|
120
123
|
end
|
121
124
|
|
122
|
-
|
123
125
|
def self.index_info(args: {}, in_format: :display_table)
|
124
126
|
data = RailsPgExtras::IndexInfo.call(args[:table_name])
|
125
127
|
|
@@ -149,7 +151,7 @@ module RailsPgExtras
|
|
149
151
|
end
|
150
152
|
|
151
153
|
def self.connection
|
152
|
-
if (db_url = ENV[
|
154
|
+
if (db_url = ENV["RAILS_PG_EXTRAS_DATABASE_URL"])
|
153
155
|
ActiveRecord::Base.establish_connection(db_url).connection
|
154
156
|
else
|
155
157
|
ActiveRecord::Base.connection
|
@@ -157,6 +159,6 @@ module RailsPgExtras
|
|
157
159
|
end
|
158
160
|
end
|
159
161
|
|
160
|
-
require
|
161
|
-
require
|
162
|
-
require
|
162
|
+
require "rails_pg_extras/web"
|
163
|
+
require "rails_pg_extras/configuration"
|
164
|
+
require "rails_pg_extras/railtie" if defined?(Rails)
|
data/rails-pg-extras.gemspec
CHANGED
@@ -1,24 +1,25 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "rails_pg_extras/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
9
|
-
s.authors
|
10
|
-
s.email
|
11
|
-
s.summary
|
12
|
-
s.description
|
13
|
-
s.homepage
|
14
|
-
s.files
|
15
|
-
s.test_files
|
7
|
+
s.name = "rails-pg-extras"
|
8
|
+
s.version = RailsPgExtras::VERSION
|
9
|
+
s.authors = ["pawurb"]
|
10
|
+
s.email = ["contact@pawelurbanek.com"]
|
11
|
+
s.summary = %q{ Rails PostgreSQL performance database insights }
|
12
|
+
s.description = %q{ Rails port of Heroku PG Extras. The goal of this project is to provide a powerful insights into PostgreSQL database for Ruby on Rails apps that are not using the default Heroku PostgreSQL plugin. }
|
13
|
+
s.homepage = "http://github.com/pawurb/rails-pg-extras"
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = s.files.grep(%r{^(spec)/})
|
16
16
|
s.require_paths = ["lib"]
|
17
|
-
s.license
|
17
|
+
s.license = "MIT"
|
18
18
|
s.add_dependency "ruby-pg-extras", RailsPgExtras::VERSION
|
19
19
|
s.add_dependency "rails"
|
20
20
|
s.add_development_dependency "rake"
|
21
21
|
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "rufo"
|
22
23
|
|
23
24
|
if s.respond_to?(:metadata=)
|
24
25
|
s.metadata = { "rubygems_mfa_required" => "true" }
|
data/spec/smoke_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "spec_helper"
|
4
|
+
require "rails-pg-extras"
|
5
5
|
|
6
6
|
describe RailsPgExtras do
|
7
7
|
RailsPgExtras::QUERIES.each do |query_name|
|
@@ -9,7 +9,7 @@ describe RailsPgExtras do
|
|
9
9
|
expect do
|
10
10
|
RailsPgExtras.run_query(
|
11
11
|
query_name: query_name,
|
12
|
-
in_format: :hash
|
12
|
+
in_format: :hash,
|
13
13
|
)
|
14
14
|
end.not_to raise_error
|
15
15
|
end
|
@@ -35,12 +35,13 @@ describe RailsPgExtras do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
it "supports custom RAILS_PG_EXTRAS_DATABASE_URL" do
|
38
|
-
ENV[
|
38
|
+
ENV["RAILS_PG_EXTRAS_DATABASE_URL"] = ENV["DATABASE_URL"]
|
39
|
+
puts ENV["RAILS_PG_EXTRAS_DATABASE_URL"]
|
39
40
|
|
40
41
|
expect do
|
41
42
|
RailsPgExtras.calls
|
42
43
|
end.not_to raise_error
|
43
44
|
|
44
|
-
ENV[
|
45
|
+
ENV["RAILS_PG_EXTRAS_DATABASE_URL"] = nil
|
45
46
|
end
|
46
47
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,23 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require_relative
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler/setup"
|
5
|
+
require "active_record"
|
6
|
+
require_relative "../lib/rails-pg-extras"
|
7
7
|
|
8
8
|
pg_version = ENV["PG_VERSION"]
|
9
9
|
|
10
|
-
port = if pg_version == "
|
11
|
-
|
12
|
-
elsif pg_version == "
|
13
|
-
|
14
|
-
elsif pg_version == "
|
15
|
-
|
16
|
-
elsif pg_version == "
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
port = if pg_version == "12"
|
11
|
+
"5432"
|
12
|
+
elsif pg_version == "13"
|
13
|
+
"5433"
|
14
|
+
elsif pg_version == "14"
|
15
|
+
"5434"
|
16
|
+
elsif pg_version == "15"
|
17
|
+
"5435"
|
18
|
+
elsif pg_version == "16"
|
19
|
+
"5436"
|
20
|
+
elsif pg_version == "17"
|
21
|
+
"5437"
|
22
|
+
else
|
23
|
+
"5432"
|
24
|
+
end
|
21
25
|
|
22
26
|
ENV["DATABASE_URL"] ||= "postgresql://postgres:secret@localhost:#{port}/rails-pg-extras-test"
|
23
27
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-pg-extras
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pawurb
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-pg-extras
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.
|
19
|
+
version: 5.4.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.
|
26
|
+
version: 5.4.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rufo
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
description: " Rails port of Heroku PG Extras. The goal of this project is to provide
|
70
84
|
a powerful insights into PostgreSQL database for Ruby on Rails apps that are not
|
71
85
|
using the default Heroku PostgreSQL plugin. "
|
@@ -132,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
146
|
- !ruby/object:Gem::Version
|
133
147
|
version: '0'
|
134
148
|
requirements: []
|
135
|
-
rubygems_version: 3.
|
149
|
+
rubygems_version: 3.5.4
|
136
150
|
signing_key:
|
137
151
|
specification_version: 4
|
138
152
|
summary: Rails PostgreSQL performance database insights
|