11# frozen_string_literal: true
22
33require 'appmap/event'
4+ require 'appmap/hook/method'
45
56module AppMap
67 module Handler
@@ -21,6 +22,7 @@ def to_h
2122 sql : payload [ :sql ] ,
2223 database_type : payload [ :database_type ]
2324 } . tap do |sql_query |
25+ sql_query [ :query_plan ] = payload [ :query_plan ] if payload [ :query_plan ]
2426 %i[ server_version ] . each do |attribute |
2527 sql_query [ attribute ] = payload [ attribute ] if payload [ attribute ]
2628 end
@@ -44,15 +46,30 @@ def examine(payload, sql:)
4446 return unless ( examiner = build_examiner )
4547
4648 if AppMap . explain_queries? && examiner . in_transaction? && examiner . database_type == :postgres
47- if sql =~ /\A (SELECT|INSERT|DELETE|UPDATE|WITH)/i
48- examiner . execute_query 'SAVEPOINT appmap_sql_examiner'
49- begin
50- plan = examiner . execute_query ( %(EXPLAIN #{ sql } ) )
51- payload [ :query_plan ] = plan . map { |line | line [ :'QUERY PLAN' ] } . join ( "\n " )
52- examiner . execute_query 'RELEASE SAVEPOINT appmap_sql_examiner'
53- rescue
54- warn "Exception occurred explaining query: #{ $!} "
55- examiner . execute_query 'ROLLBACK TO SAVEPOINT appmap_sql_examiner'
49+ if sql =~ /\A (SELECT|INSERT|UPDATE|DELETE|WITH)/i
50+ savepoint_established = \
51+ begin
52+ examiner . execute_query 'SAVEPOINT appmap_sql_examiner'
53+ true
54+ rescue
55+ # Probably: Sequel::DatabaseError: PG::InFailedSqlTransaction
56+ byebug
57+ warn $!
58+ false
59+ end
60+
61+ if savepoint_established
62+ plan = nil
63+ begin
64+ plan = examiner . execute_query ( %(EXPLAIN #{ sql } ) )
65+ rescue
66+ warn "Exception occurred explaining query: #{ $!} "
67+ examiner . execute_query 'ROLLBACK TO SAVEPOINT appmap_sql_examiner'
68+ end
69+ if plan
70+ payload [ :query_plan ] = plan . map { |line | line [ :'QUERY PLAN' ] } . join ( "\n " )
71+ examiner . execute_query 'RELEASE SAVEPOINT appmap_sql_examiner'
72+ end
5673 end
5774 end
5875 end
@@ -124,6 +141,8 @@ def execute_query(sql)
124141 def call ( _ , started , finished , _ , payload ) # (name, started, finished, unique_id, payload)
125142 return if AppMap . tracing . empty?
126143
144+ return if Thread . current [ AppMap ::Hook ::Method ::HOOK_DISABLE_KEY ] == true
145+
127146 reentry_key = "#{ self . class . name } #call"
128147 return if Thread . current [ reentry_key ] == true
129148
0 commit comments