schema_reaper 1.0.11 → 1.0.12
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 +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/schema_reaper/reporters/markdown.rb +13 -8
- data/lib/schema_reaper/reporters/reclaim.rb +47 -0
- data/lib/schema_reaper/reporters/table.rb +2 -11
- data/lib/schema_reaper/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b7e70e2066753282ad6757f3d73175a57b73b7026aa8879314f693dafc8547e7
|
|
4
|
+
data.tar.gz: d4b2ac7a4e6934e068d79ac32f694a5bffcd329bed689c23d0a080266b8bdb6b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '04943ff8915c5a809a9f81741f14e98712a6453dcf046441b7ae10d726031a994045e9490b5a8a62f948210c0e030825429bde387f35ffc15176a6b419e5f57a'
|
|
7
|
+
data.tar.gz: da080808761005f66096458968fc7c68d3c6f3251d2c97aa50a56020a37abb0d673129782244e880473ffb6287df191418f1142e1bc7632e4da05f49def17cc2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.12] - 2026-09-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **`--format markdown` claimed `0 B reclaimable` when the row count was
|
|
7
|
+
unknown.** `Table` learned in 1.0.11 that `reclaimable_bytes` is `nil`
|
|
8
|
+
both when the true value is zero and when the row count has never been
|
|
9
|
+
measured, and that a report should say which. `Markdown` summed the raw
|
|
10
|
+
bytes directly and always printed a total, so on an unanalysed database
|
|
11
|
+
it stated there was nothing to reclaim — the exact claim the 1.0.11 fix
|
|
12
|
+
was written to stop, just in the one format meant for an unattended PR
|
|
13
|
+
comment or CI job summary. The per-row `Reclaims` column had the same
|
|
14
|
+
bug: an unmeasured finding showed `0.0 B`, indistinguishable from one
|
|
15
|
+
that genuinely frees nothing. The summary/unmeasured logic now lives in
|
|
16
|
+
one shared `Reporters::Reclaim` module used by both reporters, so the
|
|
17
|
+
two formats cannot answer the same question differently again. (#7,
|
|
18
|
+
mitkush)
|
|
19
|
+
|
|
3
20
|
## [1.0.11] - 2026-09-15
|
|
4
21
|
|
|
5
22
|
Everything below landed after 1.0.10 was cut, so 1.0.10 on RubyGems contains
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "
|
|
3
|
+
require_relative "reclaim"
|
|
4
4
|
|
|
5
5
|
module SchemaReaper
|
|
6
6
|
module Reporters
|
|
@@ -18,8 +18,7 @@ module SchemaReaper
|
|
|
18
18
|
return
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
@io.puts "\n#{
|
|
22
|
-
"~**#{Bytes.human(total)}** reclaimable.\n\n"
|
|
21
|
+
@io.puts "\n#{summary_line}\n\n"
|
|
23
22
|
@io.puts "| Severity | Confidence | Type | Target | Reclaims | Fix |"
|
|
24
23
|
@io.puts "|---|---|---|---|---|---|"
|
|
25
24
|
rows.each { |r| @io.puts r }
|
|
@@ -27,17 +26,23 @@ module SchemaReaper
|
|
|
27
26
|
|
|
28
27
|
private
|
|
29
28
|
|
|
29
|
+
# "54 finding(s). **~93.8 KB reclaimable.**" -- or, when the row count is
|
|
30
|
+
# unknown or the estimate is genuinely zero, no reclaim clause at all,
|
|
31
|
+
# matching the terminal report rather than claiming a number it does not
|
|
32
|
+
# have.
|
|
33
|
+
def summary_line
|
|
34
|
+
text = Reclaim.summary(@findings)
|
|
35
|
+
line = "#{@findings.size} finding(s)."
|
|
36
|
+
line + (text ? " **#{text}.**" : "")
|
|
37
|
+
end
|
|
38
|
+
|
|
30
39
|
def rows
|
|
31
40
|
@findings.sort_by { |f| -f.confidence }.map do |f|
|
|
32
41
|
target = [f.table, f.column, f.index].compact.join("`.`")
|
|
33
42
|
"| #{f.severity} | #{(f.confidence * 100).round}% | `#{f.type}` | " \
|
|
34
|
-
"`#{target}` | #{
|
|
43
|
+
"`#{target}` | #{Reclaim.cell(f)} | #{f.suggested_fix} |"
|
|
35
44
|
end
|
|
36
45
|
end
|
|
37
|
-
|
|
38
|
-
def total
|
|
39
|
-
@findings.sum(&:reclaimable_bytes)
|
|
40
|
-
end
|
|
41
46
|
end
|
|
42
47
|
end
|
|
43
48
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "bytes"
|
|
4
|
+
|
|
5
|
+
module SchemaReaper
|
|
6
|
+
module Reporters
|
|
7
|
+
# Turns a set of findings' reclaimable-bytes into a human sentence, and a
|
|
8
|
+
# single finding's into a table cell. Shared by every reporter that states
|
|
9
|
+
# a reclaim total in prose, so the answer cannot drift between formats --
|
|
10
|
+
# which is how the terminal report learned to distinguish "no bytes" from
|
|
11
|
+
# "no idea" while the Markdown report kept treating them as the same 0.
|
|
12
|
+
module Reclaim
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
# A row count is required for a byte estimate, and pg reports
|
|
16
|
+
# reltuples = -1 for a table that has never been analysed. Printing 0.0 B
|
|
17
|
+
# for an unknown reads as "nothing to gain here", a different claim.
|
|
18
|
+
def summary(findings)
|
|
19
|
+
total = findings.sum(&:reclaimable_bytes)
|
|
20
|
+
return "~#{Bytes.human(total)} reclaimable" if total.positive?
|
|
21
|
+
return nil unless unmeasured?(findings)
|
|
22
|
+
|
|
23
|
+
"reclaim estimate unavailable — run ANALYZE to populate table statistics"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# True when some finding's byte estimate is unknown rather than zero.
|
|
27
|
+
# bytes_per_row.zero? findings (missing_fk_index, duplicate_index -- they
|
|
28
|
+
# add or drop an index, not data) always reclaim 0 regardless of row
|
|
29
|
+
# count, so an unknown row count does not make their answer unmeasured.
|
|
30
|
+
def unmeasured?(findings)
|
|
31
|
+
findings.any? { |f| f.bytes_per_row.to_i.positive? && !f.reclaim_known? }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Per-finding cell for a table row: the human size, or a note that it is
|
|
35
|
+
# not known, using the same bytes_per_row-zero exception as summary.
|
|
36
|
+
def cell(finding)
|
|
37
|
+
return Bytes.human(finding.reclaimable_bytes) if measured?(finding)
|
|
38
|
+
|
|
39
|
+
"unknown"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def measured?(finding)
|
|
43
|
+
finding.bytes_per_row.to_i.zero? || finding.reclaim_known?
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "bytes"
|
|
4
4
|
require_relative "ansi"
|
|
5
5
|
require_relative "rollup"
|
|
6
|
+
require_relative "reclaim"
|
|
6
7
|
|
|
7
8
|
module SchemaReaper
|
|
8
9
|
module Reporters
|
|
@@ -57,18 +58,8 @@ module SchemaReaper
|
|
|
57
58
|
.map { |t, n| "#{t} #{n}" }.join(" · ")
|
|
58
59
|
end
|
|
59
60
|
|
|
60
|
-
# A reclaim estimate needs a row count, and pg reports reltuples = -1 for
|
|
61
|
-
# a table it has never analysed. Printing 0.0 B for an unknown reads as
|
|
62
|
-
# "nothing to gain here", which is a different claim entirely.
|
|
63
61
|
def reclaim_text
|
|
64
|
-
|
|
65
|
-
return nil unless unmeasured?
|
|
66
|
-
|
|
67
|
-
"reclaim estimate unavailable — run ANALYZE to populate table statistics"
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def unmeasured?
|
|
71
|
-
@findings.any? { |f| f.bytes_per_row.to_i.positive? && !f.reclaim_known? }
|
|
62
|
+
Reclaim.summary(@findings)
|
|
72
63
|
end
|
|
73
64
|
|
|
74
65
|
def rolled_up
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: schema_reaper
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- aksshatt
|
|
@@ -130,6 +130,7 @@ files:
|
|
|
130
130
|
- lib/schema_reaper/reporters/console.rb
|
|
131
131
|
- lib/schema_reaper/reporters/json.rb
|
|
132
132
|
- lib/schema_reaper/reporters/markdown.rb
|
|
133
|
+
- lib/schema_reaper/reporters/reclaim.rb
|
|
133
134
|
- lib/schema_reaper/reporters/rollup.rb
|
|
134
135
|
- lib/schema_reaper/reporters/sarif.rb
|
|
135
136
|
- lib/schema_reaper/reporters/table.rb
|