Class: PgCanary::Rules::QueryComplexity

Inherits:
Base
  • Object
show all
Defined in:
lib/pg_canary/rules/definitions/query_complexity.rb

Overview

Tier 2 (opt-in): "spaghetti query" guard — too many joins or too much subquery nesting. Thresholds:

config.rules.query_complexity.max_joins (default 8)
config.rules.query_complexity.max_depth (default 4)

Constant Summary

Constants included from PgQuerySupport

PgQuerySupport::COMPARISON_OPS

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

all, #enabled?, rule_name

Class Method Details

.optionsObject



14
15
16
# File 'lib/pg_canary/rules/definitions/query_complexity.rb', line 14

def self.options
  { max_joins: 8, max_depth: 4 }
end

Instance Method Details

#check(query) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/pg_canary/rules/definitions/query_complexity.rb', line 18

def check(query)
  max_joins = rule_config(query).max_joins
  max_depth = rule_config(query).max_depth
  stmt = query.parse_result.tree.stmts.first&.stmt
  return [] unless stmt

  problems = []
  joins = count_joins(stmt)
  depth = max_select_depth(stmt)
  problems << "#{joins} joins (max #{max_joins})" if joins > max_joins
  problems << "subquery depth #{depth} (max #{max_depth})" if depth > max_depth
  return [] if problems.empty?

  [detection(
    query,
    message: "Query complexity exceeds thresholds: #{problems.join(", ")}.",
    suggestion: "Consider splitting the query, precomputing intermediate results, " \
                "or reviewing whether every join/subquery is necessary."
  )]
end

#default_enabledObject



10
11
12
# File 'lib/pg_canary/rules/definitions/query_complexity.rb', line 10

def default_enabled
  false
end