Class: PgCanary::Rules::DeepOffset
- Defined in:
- lib/pg_canary/rules/definitions/deep_offset.rb
Overview
OFFSET-based pagination reads and throws away every skipped row, so deep pages degrade linearly. The offset value is read from the runtime bind ($n), which static SQL linters cannot do. Threshold: config.rules.deep_offset.threshold (default 1000).
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
#check ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/pg_canary/rules/definitions/deep_offset.rb', line 15 def check threshold = rule_config.threshold detections = [] each_scope do |scope| next unless scope.stmt.limit_offset value = numeric_value(scope.stmt.limit_offset) next unless value && value >= threshold detections << detection( table: scope.tables.length == 1 ? scope.tables.first : nil, message: "OFFSET #{value} reads and discards #{value} rows before returning anything — " \ "offset pagination degrades linearly with page depth.", suggestion: <<~SUGGESTION.chomp Consider keyset pagination instead: WHERE (created_at, id) < (:last_seen_created_at, :last_seen_id) ORDER BY created_at DESC, id DESC LIMIT n SUGGESTION ) end detections end |