Class: Gitlab::Sherlock::Query

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/sherlock/query.rb

Constant Summary collapse

PREFIX_NEWLINE =

SQL identifiers that should be prefixed with newlines.

/
        \s+(FROM
|(LEFT|RIGHT)?INNER\s+JOIN
|(LEFT|RIGHT)?OUTER\s+JOIN
|WHERE
|AND
|GROUP\s+BY
|ORDER\s+BY
|LIMIT
|OFFSET)\s+/ix

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query, started_at, finished_at) ⇒ Query

query - The SQL query as a String (without placeholders). started_at - The start time of the query as a Time-like object. finished_at - The completion time of the query as a Time-like object.


41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/gitlab/sherlock/query.rb', line 41

def initialize(query, started_at, finished_at)
  @id = SecureRandom.uuid
  @query = query
  @started_at = started_at
  @finished_at = finished_at
  @backtrace = caller_locations.map do |loc|
    Location.from_ruby_location(loc)
  end

  unless @query.end_with?(';')
    @query += ';'
  end
end

Instance Attribute Details

#backtraceObject (readonly)

Returns the value of attribute backtrace


4
5
6
# File 'lib/gitlab/sherlock/query.rb', line 4

def backtrace
  @backtrace
end

#finished_atObject (readonly)

Returns the value of attribute finished_at


4
5
6
# File 'lib/gitlab/sherlock/query.rb', line 4

def finished_at
  @finished_at
end

#idObject (readonly)

Returns the value of attribute id


4
5
6
# File 'lib/gitlab/sherlock/query.rb', line 4

def id
  @id
end

#queryObject (readonly)

Returns the value of attribute query


4
5
6
# File 'lib/gitlab/sherlock/query.rb', line 4

def query
  @query
end

#started_atObject (readonly)

Returns the value of attribute started_at


4
5
6
# File 'lib/gitlab/sherlock/query.rb', line 4

def started_at
  @started_at
end

Class Method Details

.new_with_bindings(query, bindings, started_at, finished_at) ⇒ Object

Creates a new Query using a String and a separate Array of bindings.

query - A String containing a SQL query, optionally with numeric

placeholders (`$1`, `$2`, etc).

bindings - An Array of ActiveRecord columns and their values. started_at - The start time of the query as a Time-like object. finished_at - The completion time of the query as a Time-like object.

Returns a new Query object.


28
29
30
31
32
33
34
35
36
# File 'lib/gitlab/sherlock/query.rb', line 28

def self.new_with_bindings(query, bindings, started_at, finished_at)
  bindings.each_with_index do |(_, value), index|
    quoted_value = ActiveRecord::Base.connection.quote(value)

    query = query.gsub("$#{index + 1}", quoted_value)
  end

  new(query, started_at, finished_at)
end

Instance Method Details

#application_backtraceObject

Returns an Array of application frames (excluding Gems and the likes).


75
76
77
# File 'lib/gitlab/sherlock/query.rb', line 75

def application_backtrace
  @application_backtrace ||= @backtrace.select(&:application?)
end

#durationObject

Returns the query duration in milliseconds.


56
57
58
# File 'lib/gitlab/sherlock/query.rb', line 56

def duration
  @duration ||= (@finished_at - @started_at) * 1000.0
end

#explainObject

Returns the query plan as a String.


80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/gitlab/sherlock/query.rb', line 80

def explain
  unless @explain
    ActiveRecord::Base.connection.transaction do
      @explain = raw_explain(@query).values.flatten.join("\n")

      # Roll back any queries that mutate data so we don't mess up
      # anything when running explain on an INSERT, UPDATE, DELETE, etc.
      raise ActiveRecord::Rollback
    end
  end

  @explain
end

#formatted_queryObject

Returns a human readable version of the query.


65
66
67
# File 'lib/gitlab/sherlock/query.rb', line 65

def formatted_query
  @formatted_query ||= format_sql(@query)
end

#last_application_frameObject

Returns the last application frame of the backtrace.


70
71
72
# File 'lib/gitlab/sherlock/query.rb', line 70

def last_application_frame
  @last_application_frame ||= @backtrace.find(&:application?)
end

#to_paramObject


60
61
62
# File 'lib/gitlab/sherlock/query.rb', line 60

def to_param
  @id
end