ruby-pg-extras 5.3.1 → 5.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79aedbc5d3b30aadde2362bceebac04fe7bc3d3a27e8fc47f1f6b6c0ae287616
4
- data.tar.gz: ceea8978021edc90088a012a1fec34c0502da15f5ce60356074d741bcbc82682
3
+ metadata.gz: 809377163a6ca42ea4b8b0087e1d4ede8cfe326d0ee10a85a32df4d6f0e447f5
4
+ data.tar.gz: 295812fd83c470552c330bcf520749ebfcd6574270c7f2ee7d58d74c0877b968
5
5
  SHA512:
6
- metadata.gz: 6cd117553f43c9b211cb07e313f2b83932992a38e5217bdee70dd9d3688e441919bc0dd5a3db32cd7dc20a5c35dddd7b61e34a26ba403f690f3a9d3531a16eb4
7
- data.tar.gz: 484c04040d0d1579ce01e9874fd7f7df4dbc6209f3e262e55fc6b77246072c1315962e223f915b5311fe08a89268f7ac0193a04e50179307001ac37e5690f0e4
6
+ metadata.gz: bf48947fd5d74c8e7052cfcf9383521366887e22b7206cc4f830c91cbc17fa75db07279240d6a611febc0b7af6a9f03b9db7431b4a3b21cb80c416becaa13e2f
7
+ data.tar.gz: 1aa0b28a52a83e76f31a5101af38fa006f07ab2180980d3d149206925eba96ca76a7589cf194e534f621e32513fe7c313d45137933824a6600b86bb42295849d
@@ -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@v3
18
- - name: Run PostgreSQL 11
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=ruby-pg-extras-test \
22
22
  --env POSTGRES_PASSWORD=secret \
23
- -d -p 5432:5432 postgres:11.18-alpine \
23
+ -d -p 5432:5432 postgres:12.20-alpine \
24
24
  postgres -c shared_preload_libraries=pg_stat_statements
25
- - name: Run PostgreSQL 12
25
+ - name: Run PostgreSQL 13
26
26
  run: |
27
27
  docker run --env POSTGRES_USER=postgres \
28
28
  --env POSTGRES_DB=ruby-pg-extras-test \
29
29
  --env POSTGRES_PASSWORD=secret \
30
- -d -p 5433:5432 postgres:12.13-alpine \
30
+ -d -p 5433:5432 postgres:13.16-alpine \
31
31
  postgres -c shared_preload_libraries=pg_stat_statements
32
- - name: Run PostgreSQL 13
32
+ - name: Run PostgreSQL 14
33
33
  run: |
34
34
  docker run --env POSTGRES_USER=postgres \
35
35
  --env POSTGRES_DB=ruby-pg-extras-test \
36
36
  --env POSTGRES_PASSWORD=secret \
37
- -d -p 5434:5432 postgres:13.9-alpine \
37
+ -d -p 5434:5432 postgres:14.13-alpine \
38
38
  postgres -c shared_preload_libraries=pg_stat_statements
39
- - name: Run PostgreSQL 14
39
+ - name: Run PostgreSQL 15
40
40
  run: |
41
41
  docker run --env POSTGRES_USER=postgres \
42
42
  --env POSTGRES_DB=ruby-pg-extras-test \
43
43
  --env POSTGRES_PASSWORD=secret \
44
- -d -p 5435:5432 postgres:14.6-alpine \
44
+ -d -p 5435:5432 postgres:15.8-alpine \
45
45
  postgres -c shared_preload_libraries=pg_stat_statements
46
- - name: Run PostgreSQL 15
46
+ sleep 15
47
+ - name: Run PostgreSQL 16
48
+ run: |
49
+ docker run --env POSTGRES_USER=postgres \
50
+ --env POSTGRES_DB=ruby-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=ruby-pg-extras-test \
50
59
  --env POSTGRES_PASSWORD=secret \
51
- -d -p 5436:5432 postgres:15.1-alpine \
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 update --system
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 11
76
+ - name: Run tests for PG 12
69
77
  env:
70
- PG_VERSION: 11
78
+ PG_VERSION: 12
71
79
  POSTGRES_HOST: localhost
72
80
  POSTGRES_USER: postgres
73
81
  POSTGRES_DB: ruby-pg-extras-test
74
82
  POSTGRES_PASSWORD: secret
75
- DATABASE_URL: postgresql://postgres:secret@localhost:5432/ruby-pg-extras-test
76
83
  run: |
77
84
  bundle exec rspec spec/
78
- - name: Run tests for PG 11
85
+ - name: Run tests for PG 13
79
86
  env:
80
- PG_VERSION: 11
87
+ PG_VERSION: 13
81
88
  POSTGRES_HOST: localhost
82
89
  POSTGRES_USER: postgres
83
90
  POSTGRES_DB: ruby-pg-extras-test
84
91
  POSTGRES_PASSWORD: secret
85
- DATABASE_URL: postgresql://postgres:secret@localhost:5432/ruby-pg-extras-test
86
92
  run: |
87
93
  bundle exec rspec spec/
88
- - name: Run tests for PG 12
94
+ - name: Run tests for PG 14
89
95
  env:
90
- PG_VERSION: 12
96
+ PG_VERSION: 14
91
97
  POSTGRES_HOST: localhost
92
98
  POSTGRES_USER: postgres
93
99
  POSTGRES_DB: ruby-pg-extras-test
94
100
  POSTGRES_PASSWORD: secret
95
- DATABASE_URL: postgresql://postgres:secret@localhost:5433/ruby-pg-extras-test
96
101
  run: |
97
102
  bundle exec rspec spec/
98
- - name: Run tests for PG 13
103
+ - name: Run tests for PG 15
99
104
  env:
100
- PG_VERSION: 13
105
+ PG_VERSION: 15
101
106
  POSTGRES_HOST: localhost
102
107
  POSTGRES_USER: postgres
103
108
  POSTGRES_DB: ruby-pg-extras-test
104
109
  POSTGRES_PASSWORD: secret
105
- DATABASE_URL: postgresql://postgres:secret@localhost:5434/ruby-pg-extras-test
106
110
  run: |
107
111
  bundle exec rspec spec/
108
- - name: Run tests for PG 14
112
+ - name: Run tests for PG 16
109
113
  env:
110
- PG_VERSION: 14
114
+ PG_VERSION: 16
111
115
  POSTGRES_HOST: localhost
112
116
  POSTGRES_USER: postgres
113
117
  POSTGRES_DB: ruby-pg-extras-test
114
118
  POSTGRES_PASSWORD: secret
115
- DATABASE_URL: postgresql://postgres:secret@localhost:5435/ruby-pg-extras-test
116
119
  run: |
117
120
  bundle exec rspec spec/
118
- - name: Run tests for PG 15
121
+ - name: Run tests for PG 17
119
122
  env:
120
- PG_VERSION: 15
123
+ PG_VERSION: 17
121
124
  POSTGRES_HOST: localhost
122
125
  POSTGRES_USER: postgres
123
126
  POSTGRES_DB: ruby-pg-extras-test
124
127
  POSTGRES_PASSWORD: secret
125
- DATABASE_URL: postgresql://postgres:secret@localhost:5436/ruby-pg-extras-test
126
128
  run: |
127
129
  bundle exec rspec spec/
128
130
 
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
data/README.md CHANGED
@@ -10,6 +10,8 @@ Alternative versions:
10
10
 
11
11
  - [Ruby on Rails](https://github.com/pawurb/rails-pg-extras)
12
12
 
13
+ - [Rust](https://github.com/pawurb/rust-pg-extras)
14
+
13
15
  - [NodeJS](https://github.com/pawurb/node-postgres-extras)
14
16
 
15
17
  - [Elixir](https://github.com/pawurb/ecto_psql_extras)
@@ -98,6 +100,8 @@ RubyPgExtras.long_running_queries(args: { threshold: "200 milliseconds" })
98
100
 
99
101
  ```
100
102
 
103
+ You can customize the default `public` schema by setting `ENV['PG_EXTRAS_SCHEMA']` value.
104
+
101
105
  ## Diagnose report
102
106
 
103
107
  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:
@@ -437,7 +441,7 @@ This command displays the total size of each table and materialized view in the
437
441
 
438
442
  ```ruby
439
443
 
440
- RubyPgExtras.unused_indexes(args: { max_scans: 20 })
444
+ RubyPgExtras.unused_indexes(args: { max_scans: 50 })
441
445
 
442
446
  table | index | index_size | index_scans
443
447
  ---------------------+--------------------------------------------+------------+-------------
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
- require 'rspec/core/rake_task'
2
+ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- desc 'Test all PG versions'
6
+ desc "Test all PG versions"
7
7
  task :test_all do
8
- system("PG_VERSION=11 bundle exec rspec spec/ && PG_VERSION=12 bundle exec rspec spec/ && PG_VERSION=13 bundle exec rspec spec/ && PG_VERSION=14 bundle exec rspec spec/")
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
@@ -1,8 +1,6 @@
1
- version: '3'
2
-
3
1
  services:
4
- postgres11:
5
- image: postgres:11.16-alpine
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
- postgres12:
14
- image: postgres:12.11-alpine
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
- postgres13:
23
- image: postgres:13.7-alpine
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
- postgres14:
32
- image: postgres:14.3-alpine
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: ruby-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: ruby-pg-extras-test
53
+ POSTGRES_PASSWORD: secret
54
+ ports:
55
+ - '5437:5432'
56
+
@@ -1,19 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'terminal-table'
4
- require 'uri'
5
- require 'pg'
6
- require 'ruby_pg_extras/size_parser'
7
- require 'ruby_pg_extras/diagnose_data'
8
- require 'ruby_pg_extras/diagnose_print'
9
- require 'ruby_pg_extras/index_info'
10
- require 'ruby_pg_extras/index_info_print'
11
- require 'ruby_pg_extras/table_info'
12
- require 'ruby_pg_extras/table_info_print'
3
+ require "terminal-table"
4
+ require "uri"
5
+ require "pg"
6
+ require "ruby_pg_extras/size_parser"
7
+ require "ruby_pg_extras/diagnose_data"
8
+ require "ruby_pg_extras/diagnose_print"
9
+ require "ruby_pg_extras/index_info"
10
+ require "ruby_pg_extras/index_info_print"
11
+ require "ruby_pg_extras/table_info"
12
+ require "ruby_pg_extras/table_info_print"
13
13
 
14
14
  module RubyPgExtras
15
15
  @@database_url = nil
16
16
  NEW_PG_STAT_STATEMENTS = "1.8"
17
+ PG_STAT_STATEMENTS_17 = "1.11"
17
18
 
18
19
  QUERIES = %i(
19
20
  add_extensions bloat blocking cache_hit db_settings
@@ -27,16 +28,18 @@ module RubyPgExtras
27
28
  buffercache_usage ssl_used connections
28
29
  )
29
30
 
30
- DEFAULT_SCHEMA = ENV["PG_EXTRAS_SCHEMA"] || 'public'
31
+ DEFAULT_SCHEMA = ENV["PG_EXTRAS_SCHEMA"] || "public"
31
32
 
32
33
  DEFAULT_ARGS = Hash.new({}).merge({
33
34
  calls: { limit: 10 },
34
35
  calls_legacy: { limit: 10 },
36
+ calls_17: { limit: 10 },
35
37
  long_running_queries: { threshold: "500 milliseconds" },
36
38
  locks: { limit: 20 },
37
39
  blocking: { limit: 20 },
38
40
  outliers: { limit: 10 },
39
41
  outliers_legacy: { limit: 10 },
42
+ outliers_17: { limit: 10 },
40
43
  buffercache_stats: { limit: 10 },
41
44
  buffercache_usage: { limit: 20 },
42
45
  unused_indexes: { max_scans: 50, schema: DEFAULT_SCHEMA },
@@ -50,7 +53,7 @@ module RubyPgExtras
50
53
  table_index_scans: { schema: DEFAULT_SCHEMA },
51
54
  records_rank: { schema: DEFAULT_SCHEMA },
52
55
  tables: { schema: DEFAULT_SCHEMA },
53
- kill_pid: { pid: 0 }
56
+ kill_pid: { pid: 0 },
54
57
  })
55
58
 
56
59
  QUERIES.each do |query_name|
@@ -58,7 +61,7 @@ module RubyPgExtras
58
61
  run_query(
59
62
  query_name: query_name,
60
63
  in_format: options.fetch(:in_format, :display_table),
61
- args: options.fetch(:args, {})
64
+ args: options.fetch(:args, {}),
62
65
  )
63
66
  end
64
67
  end
@@ -70,21 +73,23 @@ module RubyPgExtras
70
73
  if pg_stat_statements_ver != nil
71
74
  if Gem::Version.new(pg_stat_statements_ver) < Gem::Version.new(NEW_PG_STAT_STATEMENTS)
72
75
  query_name = "#{query_name}_legacy".to_sym
76
+ elsif Gem::Version.new(pg_stat_statements_ver) >= Gem::Version.new(PG_STAT_STATEMENTS_17)
77
+ query_name = "#{query_name}_17".to_sym
73
78
  end
74
79
  end
75
80
  end
76
81
 
77
82
  sql = if (custom_args = DEFAULT_ARGS[query_name].merge(args)) != {}
78
- sql_for(query_name: query_name) % custom_args
79
- else
80
- sql_for(query_name: query_name)
81
- end
83
+ sql_for(query_name: query_name) % custom_args
84
+ else
85
+ sql_for(query_name: query_name)
86
+ end
82
87
  result = connection.exec(sql)
83
88
 
84
89
  display_result(
85
90
  result,
86
91
  title: description_for(query_name: query_name),
87
- in_format: in_format
92
+ in_format: in_format,
88
93
  )
89
94
  end
90
95
 
@@ -140,15 +145,15 @@ module RubyPgExtras
140
145
  result
141
146
  when :display_table
142
147
  headings = if result.count > 0
143
- result[0].keys
144
- else
145
- ["No results"]
146
- end
148
+ result[0].keys
149
+ else
150
+ ["No results"]
151
+ end
147
152
 
148
153
  puts Terminal::Table.new(
149
154
  title: title,
150
155
  headings: headings,
151
- rows: result.values
156
+ rows: result.values,
152
157
  )
153
158
  else
154
159
  raise "Invalid in_format option"
@@ -22,7 +22,7 @@ module RubyPgExtras
22
22
  :unused_indexes,
23
23
  :null_indexes,
24
24
  :bloat,
25
- :duplicate_indexes
25
+ :duplicate_indexes,
26
26
  ].yield_self do |checks|
27
27
  extensions_data = query_module.extensions(in_format: :hash)
28
28
 
@@ -66,12 +66,12 @@ module RubyPgExtras
66
66
  if table_cache_hit_ratio > min_expected
67
67
  {
68
68
  ok: true,
69
- message: "Table cache hit ratio is correct: #{table_cache_hit_ratio}."
69
+ message: "Table cache hit ratio is correct: #{table_cache_hit_ratio}.",
70
70
  }
71
71
  else
72
72
  {
73
73
  ok: false,
74
- message: "Table hit ratio is too low: #{table_cache_hit_ratio}."
74
+ message: "Table hit ratio is too low: #{table_cache_hit_ratio}.",
75
75
  }
76
76
  end
77
77
  end
@@ -87,12 +87,12 @@ module RubyPgExtras
87
87
  if index_cache_hit_ratio > min_expected
88
88
  {
89
89
  ok: true,
90
- message: "Index hit ratio is correct: #{index_cache_hit_ratio}."
90
+ message: "Index hit ratio is correct: #{index_cache_hit_ratio}.",
91
91
  }
92
92
  else
93
93
  {
94
94
  ok: false,
95
- message: "Index hit ratio is too low: #{index_cache_hit_ratio}."
95
+ message: "Index hit ratio is too low: #{index_cache_hit_ratio}.",
96
96
  }
97
97
  end
98
98
  end
@@ -103,12 +103,12 @@ module RubyPgExtras
103
103
  if ssl_connection
104
104
  {
105
105
  ok: true,
106
- message: "Database client is using a secure SSL connection."
106
+ message: "Database client is using a secure SSL connection.",
107
107
  }
108
108
  else
109
109
  {
110
110
  ok: false,
111
- message: "Database client is using an unencrypted connection."
111
+ message: "Database client is using an unencrypted connection.",
112
112
  }
113
113
  end
114
114
  end
@@ -116,7 +116,7 @@ module RubyPgExtras
116
116
  def unused_indexes
117
117
  indexes = query_module.unused_indexes(
118
118
  in_format: :hash,
119
- args: { min_scans: PG_EXTRAS_UNUSED_INDEXES_MAX_SCANS }
119
+ args: { min_scans: PG_EXTRAS_UNUSED_INDEXES_MAX_SCANS },
120
120
  ).select do |i|
121
121
  SizeParser.to_i(i.fetch("index_size").strip) >= PG_EXTRAS_UNUSED_INDEXES_MIN_SIZE_BYTES
122
122
  end
@@ -124,15 +124,15 @@ module RubyPgExtras
124
124
  if indexes.count == 0
125
125
  {
126
126
  ok: true,
127
- message: "No unused indexes detected."
127
+ message: "No unused indexes detected.",
128
128
  }
129
129
  else
130
130
  print_indexes = indexes.map do |i|
131
- "'#{i.fetch('index')}' on '#{i.fetch('table')}' size #{i.fetch('index_size')}"
131
+ "'#{i.fetch("index")}' on '#{i.fetch("table")}' size #{i.fetch("index_size")}"
132
132
  end.join(",\n")
133
133
  {
134
134
  ok: false,
135
- message: "Unused indexes detected:\n#{print_indexes}"
135
+ message: "Unused indexes detected:\n#{print_indexes}",
136
136
  }
137
137
  end
138
138
  end
@@ -140,7 +140,7 @@ module RubyPgExtras
140
140
  def null_indexes
141
141
  indexes = query_module.null_indexes(
142
142
  in_format: :hash,
143
- args: { min_relation_size_mb: PG_EXTRAS_NULL_INDEXES_MIN_SIZE_MB }
143
+ args: { min_relation_size_mb: PG_EXTRAS_NULL_INDEXES_MIN_SIZE_MB },
144
144
  ).select do |i|
145
145
  i.fetch("null_frac").gsub("%", "").to_f >= PG_EXTRAS_NULL_MIN_NULL_FRAC_PERCENT
146
146
  end
@@ -148,15 +148,15 @@ module RubyPgExtras
148
148
  if indexes.count == 0
149
149
  {
150
150
  ok: true,
151
- message: "No null indexes detected."
151
+ message: "No null indexes detected.",
152
152
  }
153
153
  else
154
154
  print_indexes = indexes.map do |i|
155
- "'#{i.fetch('index')}' size #{i.fetch('index_size')} null values fraction #{i.fetch('null_frac')}"
155
+ "'#{i.fetch("index")}' size #{i.fetch("index_size")} null values fraction #{i.fetch("null_frac")}"
156
156
  end.join(",\n")
157
157
  {
158
158
  ok: false,
159
- message: "Null indexes detected:\n#{print_indexes}"
159
+ message: "Null indexes detected:\n#{print_indexes}",
160
160
  }
161
161
  end
162
162
  end
@@ -169,16 +169,16 @@ module RubyPgExtras
169
169
  if bloat_data.count == 0
170
170
  {
171
171
  ok: true,
172
- message: "No bloat detected."
172
+ message: "No bloat detected.",
173
173
  }
174
174
  else
175
175
  print_bloat = bloat_data.map do |b|
176
- "'#{b.fetch('object_name')}' bloat #{b.fetch('bloat')} waste #{b.fetch('waste')}"
176
+ "'#{b.fetch("object_name")}' bloat #{b.fetch("bloat")} waste #{b.fetch("waste")}"
177
177
  end.join(",\n")
178
178
 
179
179
  {
180
180
  ok: false,
181
- message: "Bloat detected:\n#{print_bloat}"
181
+ message: "Bloat detected:\n#{print_bloat}",
182
182
  }
183
183
  end
184
184
  end
@@ -189,16 +189,16 @@ module RubyPgExtras
189
189
  if indexes.count == 0
190
190
  {
191
191
  ok: true,
192
- message: "No duplicate indexes detected."
192
+ message: "No duplicate indexes detected.",
193
193
  }
194
194
  else
195
195
  print_indexes = indexes.map do |i|
196
- "'#{i.fetch('idx1')}' of size #{i.fetch('size')} is identical to '#{i.fetch('idx2')}'"
196
+ "'#{i.fetch("idx1")}' of size #{i.fetch("size")} is identical to '#{i.fetch("idx2")}'"
197
197
  end.join(",\n")
198
198
 
199
199
  {
200
200
  ok: false,
201
- message: "Duplicate indexes detected:\n#{print_indexes}"
201
+ message: "Duplicate indexes detected:\n#{print_indexes}",
202
202
  }
203
203
  end
204
204
  end
@@ -211,16 +211,16 @@ module RubyPgExtras
211
211
  if queries.count == 0
212
212
  {
213
213
  ok: true,
214
- message: "No queries using significant execution ratio detected."
214
+ message: "No queries using significant execution ratio detected.",
215
215
  }
216
216
  else
217
217
  print_queries = queries.map do |q|
218
- "'#{q.fetch('query').slice(0, 30)}...' called #{q.fetch('ncalls')} times, using #{q.fetch('prop_exec_time')} of total exec time."
218
+ "'#{q.fetch("query").slice(0, 30)}...' called #{q.fetch("ncalls")} times, using #{q.fetch("prop_exec_time")} of total exec time."
219
219
  end.join(",\n")
220
220
 
221
221
  {
222
222
  ok: false,
223
- message: "Queries using significant execution ratio detected:\n#{print_queries}"
223
+ message: "Queries using significant execution ratio detected:\n#{print_queries}",
224
224
  }
225
225
  end
226
226
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'terminal-table'
3
+ require "terminal-table"
4
4
 
5
5
  module RubyPgExtras
6
6
  class DiagnosePrint
@@ -17,13 +17,13 @@ module RubyPgExtras
17
17
 
18
18
  [
19
19
  colorize("[#{symbol}] - #{el.fetch(:check_name)}", color),
20
- colorize(el.fetch(:message), color)
20
+ colorize(el.fetch(:message), color),
21
21
  ]
22
22
  end
23
23
 
24
24
  puts Terminal::Table.new(
25
25
  title: title,
26
- rows: rows
26
+ rows: rows,
27
27
  )
28
28
  end
29
29
 
@@ -19,16 +19,16 @@ module RubyPgExtras
19
19
  {
20
20
  index_name: index_name,
21
21
  table_name: index_data.fetch("tablename"),
22
- columns: index_data.fetch("columns").split(',').map(&:strip),
22
+ columns: index_data.fetch("columns").split(",").map(&:strip),
23
23
  index_size: index_size_data.find do |el|
24
24
  el.fetch("name") == index_name
25
25
  end.fetch("size", "N/A"),
26
- index_scans: index_scans_data.find do |el|
26
+ index_scans: index_scans_data.find do |el|
27
27
  el.fetch("index") == index_name
28
28
  end.fetch("index_scans", "N/A"),
29
29
  null_frac: null_indexes_data.find do |el|
30
30
  el.fetch("index") == index_name
31
- end&.fetch("null_frac", "N/A")&.strip || "0.00%"
31
+ end&.fetch("null_frac", "N/A")&.strip || "0.00%",
32
32
  }
33
33
  end
34
34
  end
@@ -40,7 +40,7 @@ module RubyPgExtras
40
40
  def null_indexes_data
41
41
  @_null_indexes_data ||= query_module.null_indexes(
42
42
  in_format: :hash,
43
- args: { min_relation_size_mb: 0 }
43
+ args: { min_relation_size_mb: 0 },
44
44
  )
45
45
  end
46
46
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'terminal-table'
3
+ require "terminal-table"
4
4
 
5
5
  module RubyPgExtras
6
6
  class IndexInfoPrint
@@ -13,10 +13,10 @@ module RubyPgExtras
13
13
  [
14
14
  el.fetch(:index_name),
15
15
  el.fetch(:table_name),
16
- el.fetch(:columns).join(', '),
16
+ el.fetch(:columns).join(", "),
17
17
  el.fetch(:index_size),
18
18
  el.fetch(:index_scans),
19
- el.fetch(:null_frac)
19
+ el.fetch(:null_frac),
20
20
  ]
21
21
  end
22
22
 
@@ -27,10 +27,10 @@ module RubyPgExtras
27
27
  "Columns",
28
28
  "Index size",
29
29
  "Index scans",
30
- "Null frac"
30
+ "Null frac",
31
31
  ],
32
32
  title: title,
33
- rows: rows
33
+ rows: rows,
34
34
  )
35
35
  end
36
36
 
@@ -4,6 +4,8 @@ SELECT
4
4
  pg_stat_activity.pid,
5
5
  pg_class.relname,
6
6
  pg_locks.transactionid,
7
+ pg_locks.locktype,
8
+ pg_locks.database,
7
9
  pg_locks.granted,
8
10
  pg_locks.mode,
9
11
  pg_stat_activity.query AS query_snippet,
@@ -0,0 +1,9 @@
1
+ /* Queries that have highest frequency of execution */
2
+
3
+ SELECT query AS qry,
4
+ interval '1 millisecond' * total_exec_time AS exec_time,
5
+ to_char((total_exec_time/sum(total_exec_time) OVER()) * 100, 'FM90D0') || '%%' AS prop_exec_time,
6
+ to_char(calls, 'FM999G999G990') AS ncalls,
7
+ interval '1 millisecond' * (shared_blk_read_time + shared_blk_write_time) AS sync_io_time
8
+ FROM pg_stat_statements WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
9
+ ORDER BY calls DESC LIMIT %{limit};
@@ -4,6 +4,8 @@ SELECT
4
4
  pg_stat_activity.pid,
5
5
  pg_class.relname,
6
6
  pg_locks.transactionid,
7
+ pg_locks.locktype,
8
+ pg_locks.database,
7
9
  pg_locks.granted,
8
10
  pg_locks.mode,
9
11
  pg_stat_activity.query AS query_snippet,
@@ -0,0 +1,10 @@
1
+ /* Queries that have longest execution time in aggregate */
2
+
3
+ SELECT interval '1 millisecond' * total_exec_time AS total_exec_time,
4
+ to_char((total_exec_time/sum(total_exec_time) OVER()) * 100, 'FM90D0') || '%%' AS prop_exec_time,
5
+ to_char(calls, 'FM999G999G999G990') AS ncalls,
6
+ interval '1 millisecond' * (shared_blk_read_time + shared_blk_write_time) AS sync_io_time,
7
+ query AS query
8
+ FROM pg_stat_statements WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
9
+ ORDER BY total_exec_time DESC
10
+ LIMIT %{limit};
@@ -10,7 +10,7 @@ module RubyPgExtras
10
10
  end
11
11
 
12
12
  def self.regexp_for_units(units)
13
- /\A(-?\d+)\s?(#{units.join('|')})\z/i
13
+ /\A(-?\d+)\s?(#{units.join("|")})\z/i
14
14
  end
15
15
 
16
16
  SI_UNITS = %w[bytes kB MB GB TB PB EB ZB YB].map(&:downcase).freeze
@@ -32,7 +32,7 @@ module RubyPgExtras
32
32
  return nil unless match_data
33
33
 
34
34
  exponent = units.index(match_data[2].downcase).to_i
35
- match_data[1].to_i * multiplier**exponent
35
+ match_data[1].to_i * multiplier ** exponent
36
36
  end
37
37
 
38
38
  DIGITS_ONLY_REGEXP = /\A(-?\d+)\z/.freeze
@@ -35,7 +35,7 @@ module RubyPgExtras
35
35
  end.fetch("count", "N/A"),
36
36
  indexes_scans: table_index_scans_data.find do |el|
37
37
  el.fetch("name") == table_name
38
- end.fetch("count", "N/A")
38
+ end.fetch("count", "N/A"),
39
39
  }
40
40
  end
41
41
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'terminal-table'
3
+ require "terminal-table"
4
4
 
5
5
  module RubyPgExtras
6
6
  class TableInfoPrint
@@ -17,7 +17,7 @@ module RubyPgExtras
17
17
  el.fetch(:indexes_cache_hit),
18
18
  el.fetch(:estimated_rows),
19
19
  el.fetch(:sequential_scans),
20
- el.fetch(:indexes_scans)
20
+ el.fetch(:indexes_scans),
21
21
  ]
22
22
  end
23
23
 
@@ -29,10 +29,10 @@ module RubyPgExtras
29
29
  "Indexes cache hit",
30
30
  "Estimated rows",
31
31
  "Sequential scans",
32
- "Indexes scans"
32
+ "Indexes scans",
33
33
  ],
34
34
  title: title,
35
- rows: rows
35
+ rows: rows,
36
36
  )
37
37
  end
38
38
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyPgExtras
4
- VERSION = "5.3.1"
4
+ VERSION = "5.4.1"
5
5
  end
@@ -1,24 +1,25 @@
1
1
  # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'ruby_pg_extras/version'
4
+ require "ruby_pg_extras/version"
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = "ruby-pg-extras"
8
- s.version = RubyPgExtras::VERSION
9
- s.authors = ["pawurb"]
10
- s.email = ["contact@pawelurbanek.com"]
11
- s.summary = %q{ Ruby PostgreSQL performance database insights }
12
- s.description = %q{ Ruby 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/ruby-pg-extras"
14
- s.files = `git ls-files`.split("\n")
15
- s.test_files = s.files.grep(%r{^(spec)/})
7
+ s.name = "ruby-pg-extras"
8
+ s.version = RubyPgExtras::VERSION
9
+ s.authors = ["pawurb"]
10
+ s.email = ["contact@pawelurbanek.com"]
11
+ s.summary = %q{ Ruby PostgreSQL performance database insights }
12
+ s.description = %q{ Ruby 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/ruby-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 = "MIT"
17
+ s.license = "MIT"
18
18
  s.add_dependency "pg"
19
19
  s.add_dependency "terminal-table"
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" }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe RubyPgExtras::DiagnoseData do
6
6
  subject(:result) do
@@ -14,7 +14,7 @@ describe RubyPgExtras::DiagnoseData do
14
14
  [
15
15
  { "table" => "public.plans", "index" => "index_plans_on_payer_id", "index_size" => "16 MB", "index_scans" => 0 },
16
16
  { "table" => "public.feedbacks", "index" => "index_feedbacks_on_target_id", "index_size" => "111180 bytes", "index_scans" => 1 },
17
- { "table" => "public.channels", "index" => "index_channels_on_slack_id", "index_size" => "56 MB", "index_scans" => 7}
17
+ { "table" => "public.channels", "index" => "index_channels_on_slack_id", "index_size" => "56 MB", "index_scans" => 7 },
18
18
  ]
19
19
  }
20
20
 
@@ -22,7 +22,7 @@ describe RubyPgExtras::DiagnoseData do
22
22
  [
23
23
  { "oid" => 123, "index" => "index_plans_on_payer_id", "index_size" => "16 MB", "unique" => true, "null_frac" => "00.00%", "expected_saving" => "0 kb" },
24
24
  { "oid" => 321, "index" => "index_feedbacks_on_target_id", "index_size" => "80 kB", "unique" => true, "null_frac" => "97.00%", "expected_saving" => "77 kb" },
25
- { "oid" => 231, "index" => "index_channels_on_slack_id", "index_size" => "56 MB", "unique" => true, "null_frac" => "49.99%", "expected_saving" => "28 MB" }
25
+ { "oid" => 231, "index" => "index_channels_on_slack_id", "index_size" => "56 MB", "unique" => true, "null_frac" => "49.99%", "expected_saving" => "28 MB" },
26
26
  ]
27
27
  }
28
28
 
@@ -30,19 +30,19 @@ describe RubyPgExtras::DiagnoseData do
30
30
  [
31
31
  { "type" => "table", "schemaname" => "public", "object_name" => "bloated_table_1", "bloat" => 8, "waste" => "0 kb" },
32
32
  { "type" => "table", "schemaname" => "public", "object_name" => "bloated_table_2", "bloat" => 8, "waste" => "77 kb" },
33
- { "type" => "schemaname", "public" => "index_channels_on_slack_id", "object_name" => "bloated_index", "bloat" => 11, "waste" => "28 MB" }
33
+ { "type" => "schemaname", "public" => "index_channels_on_slack_id", "object_name" => "bloated_index", "bloat" => 11, "waste" => "28 MB" },
34
34
  ]
35
35
  }
36
36
 
37
37
  expect(RubyPgExtras).to receive(:duplicate_indexes) {
38
38
  [
39
- { "size" => "128 kb", "idx1" => "users_pkey", "idx2" => "index_users_id" }
39
+ { "size" => "128 kb", "idx1" => "users_pkey", "idx2" => "index_users_id" },
40
40
  ]
41
41
  }
42
42
 
43
43
  expect(RubyPgExtras).to receive(:outliers) {
44
44
  [
45
- { "query" => "SELECT * FROM users WHERE users.age > 20 AND users.height > 160", "exec_time" => "154:39:26.431466", "prop_exec_time" => "72.2%", "ncalls" => "34,211,877", "sync_io_time" => "00:34:19.784318" }
45
+ { "query" => "SELECT * FROM users WHERE users.age > 20 AND users.height > 160", "exec_time" => "154:39:26.431466", "prop_exec_time" => "72.2%", "ncalls" => "34,211,877", "sync_io_time" => "00:34:19.784318" },
46
46
  ]
47
47
  }
48
48
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe RubyPgExtras::DiagnosePrint do
6
6
  subject(:print_result) do
@@ -12,18 +12,18 @@ describe RubyPgExtras::DiagnosePrint do
12
12
  {
13
13
  :check_name => :table_cache_hit,
14
14
  :ok => false,
15
- :message => "Table hit ratio too low: 0.906977."
15
+ :message => "Table hit ratio too low: 0.906977.",
16
16
  },
17
17
  {
18
18
  :check_name => :index_cache_hit,
19
19
  :ok => false,
20
- :message => "Index hit ratio is too low: 0.818182."
20
+ :message => "Index hit ratio is too low: 0.818182.",
21
21
  },
22
22
  {
23
23
  :check_name => :ssl_used,
24
24
  :ok => true,
25
- :message => "Database client is using a secure SSL connection."
26
- }
25
+ :message => "Database client is using a secure SSL connection.",
26
+ },
27
27
  ]
28
28
  end
29
29
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe RubyPgExtras::IndexInfo do
6
6
  subject(:result) do
@@ -13,27 +13,27 @@ describe RubyPgExtras::IndexInfo do
13
13
  expect(RubyPgExtras).to receive(:indexes) {
14
14
  [
15
15
  { "schemaname" => "public", "indexname" => "index_users_on_api_auth_token", "tablename" => "users", "columns" => "api_auth_token, column2" },
16
- {"schemaname" => "public", "indexname" => "index_teams_on_slack_id", "tablename" => "teams", "columns" => "slack_id" },
16
+ { "schemaname" => "public", "indexname" => "index_teams_on_slack_id", "tablename" => "teams", "columns" => "slack_id" },
17
17
  ]
18
18
  }
19
19
 
20
20
  expect(RubyPgExtras).to receive(:index_size) {
21
21
  [
22
22
  { "name" => "index_users_on_api_auth_token", "size" => "1744 kB" },
23
- {"name" => "index_teams_on_slack_id", "size" => "500 kB"},
23
+ { "name" => "index_teams_on_slack_id", "size" => "500 kB" },
24
24
  ]
25
25
  }
26
26
 
27
27
  expect(RubyPgExtras).to receive(:null_indexes) {
28
28
  [
29
- { "oid" => 16803, "index" => "index_users_on_api_auth_token", "index_size" => "1744 kB", "unique"=>true, "indexed_column" => "api_auth_token", "null_frac" => "25.00%", "expected_saving" => "300 kB" }
29
+ { "oid" => 16803, "index" => "index_users_on_api_auth_token", "index_size" => "1744 kB", "unique" => true, "indexed_column" => "api_auth_token", "null_frac" => "25.00%", "expected_saving" => "300 kB" },
30
30
  ]
31
31
  }
32
32
 
33
33
  expect(RubyPgExtras).to receive(:index_scans) {
34
34
  [
35
- { "schemaname" => "public", "table" => "users", "index" => "index_users_on_api_auth_token", "index_size" => "1744 kB", "index_scans"=> 0 },
36
- { "schemaname" => "public", "table" => "teams", "index" => "index_teams_on_slack_id", "index_size" => "500 kB", "index_scans"=> 0 }
35
+ { "schemaname" => "public", "table" => "users", "index" => "index_users_on_api_auth_token", "index_size" => "1744 kB", "index_scans" => 0 },
36
+ { "schemaname" => "public", "table" => "teams", "index" => "index_teams_on_slack_id", "index_size" => "500 kB", "index_scans" => 0 },
37
37
  ]
38
38
  }
39
39
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe RubyPgExtras::SizeParser do
6
6
  subject(:result) { described_class.to_i(arg) }
7
7
 
8
- describe 'SI Units' do
8
+ describe "SI Units" do
9
9
  let(:arg) { "#{num_units} #{unit}" }
10
10
 
11
11
  context "when the argument is a number followed by 'bytes', with possible case variations" do
@@ -72,7 +72,7 @@ describe RubyPgExtras::SizeParser do
72
72
  end
73
73
  end
74
74
 
75
- describe 'Binary Units' do
75
+ describe "Binary Units" do
76
76
  let(:arg) { "#{num_units} #{unit}" }
77
77
 
78
78
  context "when the argument is a number followed by 'bytes', with possible case variations" do
@@ -139,28 +139,28 @@ describe RubyPgExtras::SizeParser do
139
139
  end
140
140
  end
141
141
 
142
- context 'when the argument has only digits' do
143
- let(:arg) { '654245' }
142
+ context "when the argument has only digits" do
143
+ let(:arg) { "654245" }
144
144
 
145
145
  it { is_expected.to eq(arg.to_i) }
146
146
  end
147
147
 
148
- describe 'errors' do
149
- it 'raises an error when the argument has an invalid prefix' do
148
+ describe "errors" do
149
+ it "raises an error when the argument has an invalid prefix" do
150
150
  expect do
151
- described_class.to_i('123 qb')
151
+ described_class.to_i("123 qb")
152
152
  end.to raise_error ArgumentError
153
153
  end
154
154
 
155
- it 'raises an error when the argument does not have a unit in bytes' do
155
+ it "raises an error when the argument does not have a unit in bytes" do
156
156
  expect do
157
- described_class.to_i('123 mL')
157
+ described_class.to_i("123 mL")
158
158
  end.to raise_error ArgumentError
159
159
  end
160
160
 
161
- it 'when the argument cannot be parsed an number of units' do
161
+ it "when the argument cannot be parsed an number of units" do
162
162
  expect do
163
- described_class.to_i('1c3 MB')
163
+ described_class.to_i("1c3 MB")
164
164
  end.to raise_error ArgumentError
165
165
  end
166
166
  end
data/spec/smoke_spec.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe RubyPgExtras do
6
6
  RubyPgExtras::QUERIES.each do |query_name|
7
7
  it "#{query_name} description can be read" do
8
8
  expect do
9
9
  RubyPgExtras.description_for(
10
- query_name: query_name
10
+ query_name: query_name,
11
11
  )
12
12
  end.not_to raise_error
13
13
  end
@@ -18,7 +18,7 @@ describe RubyPgExtras do
18
18
  expect do
19
19
  RubyPgExtras.run_query(
20
20
  query_name: query_name,
21
- in_format: :hash
21
+ in_format: :hash,
22
22
  )
23
23
  end.not_to raise_error
24
24
  end
data/spec/spec_helper.rb CHANGED
@@ -1,22 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rubygems'
4
- require 'bundler/setup'
5
- require_relative '../lib/ruby-pg-extras'
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+ require_relative "../lib/ruby-pg-extras"
6
6
 
7
7
  pg_version = ENV["PG_VERSION"]
8
8
 
9
- port = if pg_version == "11"
10
- "5432"
11
- elsif pg_version == "12"
12
- "5433"
13
- elsif pg_version == "13"
14
- "5434"
15
- elsif pg_version == "14"
16
- "5435"
17
- else
18
- "5432"
19
- end
9
+ port = if pg_version == "12"
10
+ "5432"
11
+ elsif pg_version == "13"
12
+ "5433"
13
+ elsif pg_version == "14"
14
+ "5434"
15
+ elsif pg_version == "15"
16
+ "5435"
17
+ elsif pg_version == "16"
18
+ "5436"
19
+ elsif pg_version == "17"
20
+ "5437"
21
+ else
22
+ "5432"
23
+ end
20
24
 
21
25
  ENV["DATABASE_URL"] ||= "postgresql://postgres:secret@localhost:#{port}/ruby-pg-extras-test"
22
26
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe RubyPgExtras::TableInfo do
6
6
  subject(:result) do
@@ -13,14 +13,14 @@ describe RubyPgExtras::TableInfo do
13
13
  expect(RubyPgExtras).to receive(:tables) {
14
14
  [
15
15
  { "schemaname" => "public", "tablename" => "users" },
16
- { "schemaname" => "public", "tablename" => "teams" }
16
+ { "schemaname" => "public", "tablename" => "teams" },
17
17
  ]
18
18
  }
19
19
 
20
20
  expect(RubyPgExtras).to receive(:table_size) {
21
21
  [
22
22
  { "name" => "teams", "size" => "25 MB" },
23
- {"name" => "users", "size" => "250 MB"},
23
+ { "name" => "users", "size" => "250 MB" },
24
24
  ]
25
25
  }
26
26
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-pg-extras
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.1
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: 2023-12-14 00:00:00.000000000 Z
11
+ date: 2024-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -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: " Ruby 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. "
@@ -95,6 +109,7 @@ files:
95
109
  - lib/ruby_pg_extras/queries/buffercache_usage.sql
96
110
  - lib/ruby_pg_extras/queries/cache_hit.sql
97
111
  - lib/ruby_pg_extras/queries/calls.sql
112
+ - lib/ruby_pg_extras/queries/calls_17.sql
98
113
  - lib/ruby_pg_extras/queries/calls_legacy.sql
99
114
  - lib/ruby_pg_extras/queries/connections.sql
100
115
  - lib/ruby_pg_extras/queries/db_settings.sql
@@ -112,6 +127,7 @@ files:
112
127
  - lib/ruby_pg_extras/queries/mandelbrot.sql
113
128
  - lib/ruby_pg_extras/queries/null_indexes.sql
114
129
  - lib/ruby_pg_extras/queries/outliers.sql
130
+ - lib/ruby_pg_extras/queries/outliers_17.sql
115
131
  - lib/ruby_pg_extras/queries/outliers_legacy.sql
116
132
  - lib/ruby_pg_extras/queries/pg_stat_statements_reset.sql
117
133
  - lib/ruby_pg_extras/queries/records_rank.sql
@@ -159,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
175
  - !ruby/object:Gem::Version
160
176
  version: '0'
161
177
  requirements: []
162
- rubygems_version: 3.3.7
178
+ rubygems_version: 3.5.4
163
179
  signing_key:
164
180
  specification_version: 4
165
181
  summary: Ruby PostgreSQL performance database insights