Class: PoolLint::SqlWatcher

Inherits:
Object
  • Object
show all
Defined in:
lib/poollint/sql_watcher.rb

Defined Under Namespace

Classes: Detection

Constant Summary collapse

ADVISORY_PATTERN =
/
  \bpg_(?:try_)?advisory_
  (?:lock(?:_shared)?|unlock(?:_shared|_all)?)\s*\(
/ix
LEADING_COMMENTS =
%r{\A(?:\s+|/\*.*?\*/|--[^\n]*(?:\n|\z))*}m
MYSQL_LOCK_OPERATIONS =
{
  "GET_LOCK" => :acquire,
  "RELEASE_LOCK" => :release,
  "RELEASE_ALL_LOCKS" => :release_all
}.freeze
MYSQL_LOCK_PATTERN =
/\b(GET_LOCK|RELEASE_LOCK|RELEASE_ALL_LOCKS)\s*\(/i
SETTING_PATTERN =
/\A[a-z_][a-z0-9_.-]*/i
SPECIAL_SETTINGS =
{
  "NAMES" => "client_encoding",
  "ROLE" => "role",
  "SCHEMA" => "search_path",
  "SESSION AUTHORIZATION" => "session_authorization",
  "TIME ZONE" => "timezone",
  "XML OPTION" => "xmloption"
}.freeze

Class Method Summary collapse

Class Method Details

.detect(sql) ⇒ Object



64
65
66
67
68
69
70
# File 'lib/poollint/sql_watcher.rb', line 64

def detect(sql)
  statement = sql.to_s.sub(LEADING_COMMENTS, "").strip
  return if statement.empty?
  return Detection.new(kind: :advisory_lock) if statement.match?(ADVISORY_PATTERN)

  detect_user_level_lock(statement) || detect_set(statement) || detect_reset(statement)
end

.install!Object



37
38
39
40
41
42
43
# File 'lib/poollint/sql_watcher.rb', line 37

def install!
  return if @subscriber

  @subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
    process(args.last)
  end
end

.process(payload) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/poollint/sql_watcher.rb', line 45

def process(payload)
  return if ExecutionState.inspecting?
  return if payload[:name] == "SCHEMA"

  connection = payload[:connection]
  detection = detect(payload[:sql])
  return unless connection && detection

  state_for(connection).mark_dirty(
    kind: detection.kind,
    setting: detection.setting,
    sql: payload[:sql],
    call_site: application_call_site,
    monitor_setting: PoolLint.configuration.track_custom_gucs,
    lock_operation: detection.lock_operation,
    lock_name: detection.lock_name
  )
end