Class: AssertEfficientSql::SqlEfficiencyAsserter

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

Instance Method Summary collapse

Constructor Details

#initialize(options, context) ⇒ SqlEfficiencyAsserter

Returns a new instance of SqlEfficiencyAsserter


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/assert_efficient_sql.rb', line 91

def initialize(options, context)
  @issues = []
  @options, @context = options, context
  @analyses = ActiveRecord::Base.connection.analyses
  @session_before = fetch_database_session
  yield
  check_for_query_statements
  @session_after = fetch_database_session
  check_session_status

  @analyses.each do |@name, @sql, @analysis|
    @analysis.each do |@explanation|
      analyze_efficiency
    end
  end

  puts explain_all  if @options[:verbose]
end

Instance Method Details

#analyze_efficiencyObject


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/assert_efficient_sql.rb', line 142

def analyze_efficiency
  rows = @explanation[:rows].to_i
  throttle = @options[:throttle]

  check rows <= throttle do
    "row count #{ rows } is more than :throttle => #{ throttle }"
  end

  check @options[:ALL] || 'ALL' != @explanation[:type] do
    'full table scan'
  end

  check @options[:Using_filesort] ||
        @explanation[:Extra] !~ /(Using filesort)/ do
    $1
  end

  flunk 'Pessimistic ' + format_explanation  unless @issues.empty?
end

#check(bool) ⇒ Object


125
126
127
# File 'lib/assert_efficient_sql.rb', line 125

def check(bool)
  @issues << yield  unless bool
end

#check_for_query_statementsObject


162
163
164
# File 'lib/assert_efficient_sql.rb', line 162

def check_for_query_statements
  flunk 'assert_efficient_sql saw no queries!'  if @analyses.empty?
end

#check_session_statusObject


129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/assert_efficient_sql.rb', line 129

def check_session_status
  @options.each do |key, value|
    if @session_before[key]  # ERGO and not true
      if (before = @session_before[key]) + value <=
         (after = @session_after[key])
        flunk "Status variable #{ key } incremented > #{ value },\n" +
              "from #{ before } to #{ after }, during one of these:\n" +
               explain_all
      end
    end
  end
end

#explain_allObject


110
111
112
113
114
# File 'lib/assert_efficient_sql.rb', line 110

def explain_all
  @analyses.map{ |@name, @sql, @analysis|
    format_explanation
  }.join("\n")
end

#fetch_database_sessionObject


116
117
118
119
120
121
122
123
# File 'lib/assert_efficient_sql.rb', line 116

def fetch_database_session
  result = ActiveRecord::Base.connection.execute('show session status')
  hashes = []
  result.each_hash{|h|  hashes << h  }
  zz = {}.with_indifferent_access
  hashes.each{|v|  zz[v['Variable_name'].to_sym] = v['Value'].to_i  }
  return zz
end

#flunk(why) ⇒ Object


166
167
168
# File 'lib/assert_efficient_sql.rb', line 166

def flunk(why)
  @context.flunk @context.build_message(@options[:diagnostic], why)
end

#format_explanationObject


170
171
172
173
174
175
176
177
# File 'lib/assert_efficient_sql.rb', line 170

def format_explanation
  @name = 'for ' + @name  unless @name.blank?

  return "\nquery #{ @name }\n" +
         @issues.join("\n") +
         "\n#{ @sql }\n   " +
         @analysis.qa_columnized
end