ruby-pg-extras 5.6.15 → 5.6.16

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: e20ed34b0677aa7e50c14ca2d5a511d4854f0eb34a1ad7e04a4f94fe2349895b
4
- data.tar.gz: ef35f2a431195ba26a0271808315b54985254df379412ffb4eef9dc4ff81f7e8
3
+ metadata.gz: 789f323a6bba1cdf366a6eb53b5102a4a0f3d43ebafb1ea2f3151451bb28bffa
4
+ data.tar.gz: 4faaa79f35aa2c32c1b7c9d7def43b9319d43bb67a3933458bec3badceb672b6
5
5
  SHA512:
6
- metadata.gz: 6145da151dc40da7d0f79a3a2c9ff3d059dd9b320e44b751f6d5a9d0b00d395a78aff3c8bd1bf51453aa65ccb7cf12953ec73e54b4a350d7ee34ec61b5f661a0
7
- data.tar.gz: 72861cc4517a977e39266f2617094db82be77ba31f932831785540c3bc3ae078e1deccbc32b5b025343bbbe2e2c2d25529e24dad170ea9e8969795dfe3ee64de
6
+ metadata.gz: 8fe626803b4d7eb880f45571998dac5fd95d0430967c8f111d56ca72891732bc957db2276579bab6063087a8241c13ac2daa28e4059bcb4ac1c6688e6e5af478
7
+ data.tar.gz: b849cd97547e4b394dc4fb6a6e0af538e8dc8c51d85653af165b944c341d0e9cf98ecb0df7607a807145a5befb67cf097f7275dde9de9303d694cb28e6e59b99
data/README.md CHANGED
@@ -118,7 +118,7 @@ Keep reading to learn about methods that `diagnose` uses under the hood.
118
118
 
119
119
  ### `missing_fk_indexes`
120
120
 
121
- This method lists columns likely to be foreign keys (i.e. column name ending in `_id` and related table exists) which don't have an index. It's recommended to always index foreign key columns because they are used for searching relation objects.
121
+ This method lists **actual foreign key columns** (based on existing foreign key constraints) which don't have a supporting index. It's recommended to always index foreign key columns because they are commonly used for lookups and join conditions.
122
122
 
123
123
  You can add indexes on the columns returned by this query and later check if they are receiving scans using the [unused_indexes method](#unused_indexes). Please remember that each index decreases write performance and autovacuuming overhead, so be careful when adding multiple indexes to often updated tables.
124
124
 
@@ -136,14 +136,34 @@ RubyPgExtras.missing_fk_indexes(args: { table_name: "users" })
136
136
 
137
137
  ```
138
138
 
139
+ You can also exclude known/intentional cases using `ignore_list` (array or comma-separated string), with entries like:
140
+ - `"posts.topic_id"` (ignore a specific table+column)
141
+ - `"topic_id"` (ignore this column name for all tables)
142
+ - `"posts.*"` (ignore all columns on a table)
143
+ - `"*"` (ignore everything)
144
+
145
+ ```ruby
146
+ RubyPgExtras.missing_fk_indexes(args: { ignore_list: ["users.company_id", "posts.*"] })
147
+ ```
148
+
139
149
  `table_name` argument is optional, if omitted, the method will display missing fk indexes for all the tables.
140
150
 
141
151
  ## `missing_fk_constraints`
142
152
 
143
- Similarly to the previous method, this one shows columns likely to be foreign keys that don't have a corresponding foreign key constraint. Foreign key constraints improve data integrity in the database by preventing relations with nonexisting objects. You can read more about the benefits of using foreign keys [in this blog post](https://pawelurbanek.com/rails-postgresql-data-integrity).
153
+ This method shows **columns that look like foreign keys** but don't have a corresponding foreign key constraint yet. Foreign key constraints improve data integrity in the database by preventing relations with nonexisting objects. You can read more about the benefits of using foreign keys [in this blog post](https://pawelurbanek.com/rails-postgresql-data-integrity).
154
+
155
+ Heuristic notes:
156
+ - A column is considered a candidate if it matches `<table_singular>_id` and the related table exists (underscored prefixes like `account_user_id` are supported).
157
+ - Rails polymorphic associations (`<name>_id` + `<name>_type`) are ignored since they cannot be expressed as real FK constraints.
158
+
159
+ You can also exclude known/intentional cases using `ignore_list` (array or comma-separated string), with entries like:
160
+ - `"posts.category_id"` (ignore a specific table+column)
161
+ - `"category_id"` (ignore this column name for all tables)
162
+ - `"posts.*"` (ignore all columns on a table)
163
+ - `"*"` (ignore everything)
144
164
 
145
165
  ```ruby
146
- RubyPgExtras.missing_fk_constraints(args: { table_name: "users" })
166
+ RubyPgExtras.missing_fk_constraints(args: { table_name: "users", ignore_list: ["users.customer_id", "posts.*"] })
147
167
 
148
168
  +---------------------------------+
149
169
  | Missing foreign key constraints |
@@ -36,7 +36,7 @@ services:
36
36
  ports:
37
37
  - '5436:5432'
38
38
  postgres17:
39
- image: postgres:17.0-alpine
39
+ image: postgres:17.7-alpine
40
40
  command: postgres -c shared_preload_libraries=pg_stat_statements
41
41
  environment:
42
42
  POSTGRES_USER: postgres
@@ -44,4 +44,13 @@ services:
44
44
  POSTGRES_PASSWORD: secret
45
45
  ports:
46
46
  - '5437:5432'
47
+ postgres18:
48
+ image: postgres:18.1-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
+ - '5438:5432'
47
56
 
@@ -192,7 +192,7 @@ module RubyPgExtras
192
192
  end
193
193
 
194
194
  def self.missing_fk_indexes(args: {}, in_format: :display_table)
195
- RubyPgExtras::MissingFkIndexes.call(args[:table_name])
195
+ RubyPgExtras::MissingFkIndexes.call(args[:table_name], ignore_list: args[:ignore_list])
196
196
  end
197
197
 
198
198
  def self.missing_fk_constraints(args: {}, in_format: :display_table)
@@ -2,11 +2,18 @@
2
2
 
3
3
  module RubyPgExtras
4
4
  class MissingFkIndexes
5
- def self.call(table_name)
6
- new.call(table_name)
5
+ # ignore_list: array (or comma-separated string) of entries like:
6
+ # - "posts.topic_id" (ignore a specific table+column)
7
+ # - "topic_id" (ignore this column name for all tables)
8
+ # - "posts.*" (ignore all columns on a table)
9
+ # - "*" (ignore everything)
10
+ def self.call(table_name, ignore_list: nil)
11
+ new.call(table_name, ignore_list: ignore_list)
7
12
  end
8
13
 
9
- def call(table_name)
14
+ def call(table_name, ignore_list: nil)
15
+ ignore_list_matcher = IgnoreList.new(ignore_list)
16
+
10
17
  indexes_info = query_module.indexes(in_format: :hash)
11
18
  foreign_keys = query_module.foreign_keys(in_format: :hash)
12
19
 
@@ -23,6 +30,9 @@ module RubyPgExtras
23
30
  table_fks.each do |fk|
24
31
  column_name = fk.fetch("column_name")
25
32
 
33
+ # Skip columns explicitly excluded via ignore list.
34
+ next if ignore_list_matcher.ignored?(table: table, column_name: column_name)
35
+
26
36
  if index_info.none? { |row| row.fetch("columns").split(",").first == column_name }
27
37
  agg.push(
28
38
  {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyPgExtras
4
- VERSION = "5.6.15"
4
+ VERSION = "5.6.16"
5
5
  end
@@ -18,4 +18,26 @@ describe "missing_fk_indexes" do
18
18
  { table: "posts", column_name: "topic_id" },
19
19
  ])
20
20
  end
21
+
22
+ it "supports ignoring a specific table+column via args" do
23
+ result = RubyPgExtras.missing_fk_indexes(
24
+ args: { ignore_list: ["posts.topic_id"] },
25
+ in_format: :hash
26
+ )
27
+
28
+ expect(result).to eq([
29
+ { table: "users", column_name: "company_id" },
30
+ ])
31
+ end
32
+
33
+ it "supports ignoring a column name globally via args" do
34
+ result = RubyPgExtras.missing_fk_indexes(
35
+ args: { ignore_list: ["company_id"] },
36
+ in_format: :hash
37
+ )
38
+
39
+ expect(result).to eq([
40
+ { table: "posts", column_name: "topic_id" },
41
+ ])
42
+ end
21
43
  end
data/spec/spec_helper.rb CHANGED
@@ -12,9 +12,10 @@ PG_PORTS = {
12
12
  "15" => "5435",
13
13
  "16" => "5436",
14
14
  "17" => "5437",
15
+ "18" => "5438",
15
16
  }
16
17
 
17
- port = PG_PORTS.fetch(pg_version, "5432")
18
+ port = PG_PORTS.fetch(pg_version, "5438")
18
19
 
19
20
  ENV["DATABASE_URL"] ||= "postgresql://postgres:secret@localhost:#{port}/ruby-pg-extras-test"
20
21
 
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.6.15
4
+ version: 5.6.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - pawurb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-12-16 00:00:00.000000000 Z
11
+ date: 2026-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg