pg_canary 0.1.0 → 0.2.0
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 +4 -0
- data/README.md +1 -8
- data/lib/pg_canary/configuration.rb +1 -14
- data/lib/pg_canary/rules/base.rb +1 -10
- data/lib/pg_canary/rules/definitions/array_search_without_gin.rb +0 -4
- data/lib/pg_canary/rules/definitions/cartesian_join.rb +0 -4
- data/lib/pg_canary/rules/definitions/correlated_subquery_in_select.rb +0 -4
- data/lib/pg_canary/rules/definitions/count_star_without_where.rb +0 -4
- data/lib/pg_canary/rules/definitions/deep_offset.rb +0 -4
- data/lib/pg_canary/rules/definitions/distinct_with_join.rb +0 -4
- data/lib/pg_canary/rules/definitions/function_on_column.rb +0 -4
- data/lib/pg_canary/rules/definitions/huge_in_list.rb +0 -4
- data/lib/pg_canary/rules/definitions/implicit_cast.rb +0 -4
- data/lib/pg_canary/rules/definitions/jsonb_search_without_gin.rb +0 -4
- data/lib/pg_canary/rules/definitions/leading_wildcard_like.rb +0 -4
- data/lib/pg_canary/rules/definitions/not_in_subquery.rb +0 -4
- data/lib/pg_canary/rules/definitions/or_across_columns.rb +0 -4
- data/lib/pg_canary/rules/definitions/order_by_random.rb +0 -4
- data/lib/pg_canary/rules/definitions/query_complexity.rb +0 -4
- data/lib/pg_canary/rules/definitions/regex_without_trgm.rb +0 -4
- data/lib/pg_canary/rules/definitions/select_star_with_heavy_columns.rb +0 -4
- data/lib/pg_canary/rules/definitions/unindexed_join.rb +0 -4
- data/lib/pg_canary/rules/definitions/unindexed_order_by_with_limit.rb +1 -5
- data/lib/pg_canary/rules/definitions/unindexed_where.rb +1 -5
- data/lib/pg_canary/rules/definitions/union_instead_of_union_all.rb +0 -4
- data/lib/pg_canary/version.rb +1 -1
- data/lib/pg_canary.rb +0 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3117b64abbdaf73701f98780b6dd794822d6bf19919365e3a7c4ffffa62b69a5
|
|
4
|
+
data.tar.gz: c1c73a9c77af75bdcbc7bd3b3685654387728986a5d1d7a880c69c7263dc4ca6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17df21da5a3d3a6f221db4aa087d4627fac79de5e8a9d4c7cd96c77849df96a47a63ea4d681a9404bd0b52274cbf7424e926cb7a84769532b8e7b81dd0daa089
|
|
7
|
+
data.tar.gz: '08302281e57605688fd0eaded8f1a2d031ebae2b5e9499d67c564aecd81e420de5d8f015b495e3a5153297e0e3113366874fe13563c78eb403db7bd3a3eb40c5'
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -62,10 +62,7 @@ config.rules.query_complexity.max_joins = 12
|
|
|
62
62
|
config.rules.select_star_with_heavy_columns.heavy_types = %w[bytea jsonb]
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
Once opted in,
|
|
66
|
-
|
|
67
|
-
1. List small tables in `config.ignore_tables`
|
|
68
|
-
2. Provide approximate production row counts in `config.table_size_hints` — when hints are present, Tier 2 rules apply **only** to tables hinted at `size_rule_threshold` (default 10,000) or above. When hints are empty, Tier 2 rules apply to every table — which is precisely why they are off by default.
|
|
65
|
+
Once opted in, keep false positives down by listing small tables in `config.ignore_tables`.
|
|
69
66
|
|
|
70
67
|
## Configuration
|
|
71
68
|
|
|
@@ -82,10 +79,6 @@ PgCanary.configure do |config|
|
|
|
82
79
|
|
|
83
80
|
# Excluding tables
|
|
84
81
|
config.ignore_tables = %w[prefectures plans schema_migrations ar_internal_metadata]
|
|
85
|
-
|
|
86
|
-
# For size-dependent (Tier 2) rules: approximate production row counts
|
|
87
|
-
config.table_size_hints = { "users" => 1_000_000, "orders" => 10_000_000 }
|
|
88
|
-
config.size_rule_threshold = 10_000 # apply Tier 2 rules only to tables hinted at or above this
|
|
89
82
|
end
|
|
90
83
|
```
|
|
91
84
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module PgCanary
|
|
4
|
-
# Global settings, exposed through PgCanary.configure.
|
|
5
4
|
class Configuration
|
|
6
5
|
# nil means "not explicitly configured" — the Railtie then enables
|
|
7
6
|
# pg_canary in development/test only.
|
|
8
7
|
attr_accessor :enabled
|
|
9
8
|
|
|
10
9
|
# False-positive controls
|
|
11
|
-
attr_accessor :ignore_tables
|
|
10
|
+
attr_accessor :ignore_tables
|
|
12
11
|
|
|
13
12
|
attr_accessor :logger, :app_root
|
|
14
13
|
attr_reader :rules
|
|
@@ -16,8 +15,6 @@ module PgCanary
|
|
|
16
15
|
def initialize
|
|
17
16
|
@enabled = nil
|
|
18
17
|
@ignore_tables = %w[schema_migrations ar_internal_metadata]
|
|
19
|
-
@table_size_hints = {}
|
|
20
|
-
@size_rule_threshold = 10_000
|
|
21
18
|
@rules = RulesConfig.new
|
|
22
19
|
@logger = nil
|
|
23
20
|
@app_root = nil
|
|
@@ -26,16 +23,6 @@ module PgCanary
|
|
|
26
23
|
def ignore_table?(table)
|
|
27
24
|
table && ignore_tables.map(&:to_s).include?(table.to_s)
|
|
28
25
|
end
|
|
29
|
-
|
|
30
|
-
# Whether a size-dependent (Tier 2) rule should look at this table.
|
|
31
|
-
# With no hints configured, every table qualifies (which is exactly why
|
|
32
|
-
# Tier 2 rules are opt-in).
|
|
33
|
-
def size_hint_allows?(table)
|
|
34
|
-
hints = table_size_hints || {}
|
|
35
|
-
return true if hints.empty?
|
|
36
|
-
|
|
37
|
-
hints[table.to_s].to_i >= size_rule_threshold
|
|
38
|
-
end
|
|
39
26
|
end
|
|
40
27
|
|
|
41
28
|
# Exposes one RuleConfig per built-in rule, both as methods and via [].
|
data/lib/pg_canary/rules/base.rb
CHANGED
|
@@ -42,23 +42,14 @@ module PgCanary
|
|
|
42
42
|
raise NotImplementedError, "#{self.class} must declare #default_enabled (true for Tier 1, false for Tier 2)"
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def size_dependent?
|
|
46
|
-
raise NotImplementedError, "#{self.class} must declare #size_dependent?"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
45
|
private
|
|
50
46
|
|
|
51
47
|
def rule_config(query)
|
|
52
48
|
query.config.rules[self.class.rule_name]
|
|
53
49
|
end
|
|
54
50
|
|
|
55
|
-
# Tier 2 gate: with size hints configured, only tables hinted as large
|
|
56
|
-
# are checked.
|
|
57
51
|
def applicable_table?(query, table)
|
|
58
|
-
|
|
59
|
-
return true unless size_dependent?
|
|
60
|
-
|
|
61
|
-
query.config.size_hint_allows?(table)
|
|
52
|
+
!query.config.ignore_table?(table)
|
|
62
53
|
end
|
|
63
54
|
|
|
64
55
|
def detection(query, message:, suggestion: nil, table: nil, columns: nil)
|
|
@@ -4,7 +4,7 @@ module PgCanary
|
|
|
4
4
|
module Rules
|
|
5
5
|
# Tier 2 (opt-in): ORDER BY x LIMIT n without an index led by x forces a
|
|
6
6
|
# full sort before the limit can apply. Size-dependent, so disabled by
|
|
7
|
-
# default
|
|
7
|
+
# default.
|
|
8
8
|
class UnindexedOrderByWithLimit < Base
|
|
9
9
|
include IndexPredicates
|
|
10
10
|
|
|
@@ -12,10 +12,6 @@ module PgCanary
|
|
|
12
12
|
false
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def size_dependent?
|
|
16
|
-
true
|
|
17
|
-
end
|
|
18
|
-
|
|
19
15
|
def check(query)
|
|
20
16
|
detections = []
|
|
21
17
|
query.each_scope do |scope|
|
|
@@ -5,16 +5,12 @@ module PgCanary
|
|
|
5
5
|
# Tier 2 (opt-in): equality/range predicates on columns with no index
|
|
6
6
|
# whose leading column could serve them. Depends on production table
|
|
7
7
|
# size — a 30-row lookup table is fine without indexes — hence disabled
|
|
8
|
-
# by default
|
|
8
|
+
# by default.
|
|
9
9
|
class UnindexedWhere < Base
|
|
10
10
|
def default_enabled
|
|
11
11
|
false
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def size_dependent?
|
|
15
|
-
true
|
|
16
|
-
end
|
|
17
|
-
|
|
18
14
|
def check(query)
|
|
19
15
|
query.each_scope.with_object([]) do |scope, detections|
|
|
20
16
|
next unless scope.where_clause
|
data/lib/pg_canary/version.rb
CHANGED
data/lib/pg_canary.rb
CHANGED
|
@@ -56,7 +56,6 @@ module PgCanary
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
if defined?(Rails::Railtie)
|
|
59
|
-
# Middleware insertion and automatic enabling in development/test.
|
|
60
59
|
class Railtie < Rails::Railtie
|
|
61
60
|
initializer "pg_canary.app_root", before: :load_config_initializers do
|
|
62
61
|
PgCanary.config.app_root ||= Rails.root.to_s
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pg_canary
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kyuuri1791
|
|
@@ -119,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
119
119
|
- !ruby/object:Gem::Version
|
|
120
120
|
version: '0'
|
|
121
121
|
requirements: []
|
|
122
|
-
rubygems_version: 3.6.
|
|
122
|
+
rubygems_version: 3.6.9
|
|
123
123
|
specification_version: 4
|
|
124
124
|
summary: Detects SQL anti-patterns that can become slow queries in production, while
|
|
125
125
|
you develop.
|