Class: PgCanary::Rules::OrderByRandom

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

Overview

ORDER BY RANDOM() sorts the entire result set just to pick rows — always suspicious regardless of table size.

Instance Method Summary collapse

Methods inherited from Base

all, check, default_enabled, enabled?, #initialize, option, options, rule_name

Constructor Details

This class inherits a constructor from PgCanary::Rules::Base

Instance Method Details

#checkObject



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

def check
  detections = []
  each_scope do |scope|
    scope.sort_items.each do |sort_by|
      func = sort_by.node&.unwrap
      next unless func.is_a?(PgQuery::FuncCall)
      next unless func.function_name == "random"

      detections << detection(
        table: scope.tables.length == 1 ? scope.tables.first : nil,
        message: "ORDER BY RANDOM() reads and sorts every row, so it gets slower " \
                 "in proportion to table size.",
        suggestion: <<~SUGGESTION.chomp
          Alternatives:
            - TABLESAMPLE: SELECT * FROM t TABLESAMPLE SYSTEM (1) LIMIT n
            - random primary-key range: WHERE id >= (SELECT (random() * max(id))::bigint FROM t) LIMIT n
        SUGGESTION
      )
    end
  end
  detections
end