Class: PgCanary::Rules::CountStarWithoutWhere

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

Overview

Tier 2 (opt-in): SELECT COUNT(*) without WHERE. Because of MVCC, PostgreSQL has no O(1) row count — this scans the whole table.

Constant Summary

Constants included from PgQuerySupport

PgQuerySupport::COMPARISON_OPS

Instance Method Summary collapse

Methods inherited from Base

all, #enabled?, options, rule_name

Instance Method Details

#check(query) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/pg_canary/rules/definitions/count_star_without_where.rb', line 12

def check(query)
  detections = []
  query.each_scope do |scope|
    stmt = scope.stmt
    next if stmt.where_clause || stmt.group_clause.any?
    next unless count_star?(stmt)

    tables = scope.tables
    next unless tables.length == 1

    table = tables.first
    next unless applicable_table?(query, table)

    detections << detection(
      query,
      table: table,
      message: "COUNT(*) without WHERE scans the whole #{table} table — PostgreSQL's MVCC " \
               "has no O(1) row count.",
      suggestion: <<~SUGGESTION.chomp
        If an approximation is acceptable, use the planner's estimate:
          SELECT reltuples::bigint FROM pg_class WHERE relname = '#{table}';
        For exact counts displayed frequently, maintain a counter cache.
      SUGGESTION
    )
  end
  detections
end

#default_enabledObject



8
9
10
# File 'lib/pg_canary/rules/definitions/count_star_without_where.rb', line 8

def default_enabled
  false
end