Class: Shiba::Query

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

Constant Summary collapse

FINGERPRINTER =
Shiba.root + "/bin/fingerprint"
@@index =
0
@@fingerprinter_mutex =
Mutex.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sql, stats) ⇒ Query

Returns a new instance of Query.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/shiba/query.rb', line 29

def initialize(sql, stats)
  @sql, _, @backtrace = sql.partition(" /*shiba")

  if @backtrace.length > 0
    @backtrace.chomp!("*/")
    @backtrace = JSON.parse(@backtrace)
  else
    @backtrace = []
  end

  @stats = stats
  @@index += 1
  @index = @@index
end

Instance Attribute Details

#backtraceObject (readonly)

Returns the value of attribute backtrace.



44
45
46
# File 'lib/shiba/query.rb', line 44

def backtrace
  @backtrace
end

#indexObject (readonly)

Returns the value of attribute index.



44
45
46
# File 'lib/shiba/query.rb', line 44

def index
  @index
end

#sqlObject (readonly)

Returns the value of attribute sql.



44
45
46
# File 'lib/shiba/query.rb', line 44

def sql
  @sql
end

Class Method Details

.get_fingerprint(query) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/shiba/query.rb', line 13

def self.get_fingerprint(query)
  @@fingerprinter_mutex.synchronize do
    if !@stdin
      @stdin, @stdout, _ = Open3.popen2(FINGERPRINTER)
    end
    @stdin.puts(query.gsub(/\n/, ' '))
    begin
      Timeout.timeout(2) do
        @stdout.readline.chomp
      end
    rescue StandardError => e
      $stderr.puts("shiba: timed out waiting for fingerprinter on #{query}...")
    end
  end
end

Instance Method Details

#aggregation?Boolean

Returns:

  • (Boolean)


77
78
79
80
81
# File 'lib/shiba/query.rb', line 77

def aggregation?
  @sql =~ /select\s*(.*?)from/i
  select_fields = $1
  select_fields =~ /(min|max|avg|count|sum|group_concat)\s*\(.*?\)/i
end

#explainObject



54
55
56
# File 'lib/shiba/query.rb', line 54

def explain
  Explain.new(self, @stats)
end

#fingerprintObject



46
47
48
# File 'lib/shiba/query.rb', line 46

def fingerprint
  @fingerprint ||= self.class.get_fingerprint(@sql)
end

#from_tableObject



58
59
60
61
62
63
64
65
66
67
# File 'lib/shiba/query.rb', line 58

def from_table
  @sql =~ /\s+from\s*([^\s,]+)/i
  table = $1
  return nil unless table

  table = table.downcase
  table.gsub!('`', '')
  table.gsub!(/.*\.(.*)/, '\1')
  table
end

#limitObject



69
70
71
72
73
74
75
# File 'lib/shiba/query.rb', line 69

def limit
  if @sql =~ /limit\s*(\d+)\s*(offset \d+)?$/i
    $1.to_i
  else
    nil
  end
end

#md5Object



50
51
52
# File 'lib/shiba/query.rb', line 50

def md5
  Digest::MD5.hexdigest(fingerprint)
end