This allows you to analyze all queries issued during testing, and see which ones were parameterized, which ones were not parameterized, and possible queries where parameterization was missed. To see this analysis, run "rake check_query_parameterization". This will run the specs logging all queries, then run a script that analyzes the logged queries. You can view the analysis in the created sql_query_parameterization_analysis.txt. The first line in this analysis has summary data: ``` Summary: Missed: 11|11, Parameterized: 1034|71461, Not Parameterized: 94|33003 ``` `Missed: 11|11` means 11 total and 11 unique queries were issued that you would expect to be parameterized but were not (missed parameterization). `Parameterized: 1034|71461` means there were 71461 total and 1034 unique parameterized queries. `Not Parameterized: 94:33003` means there were 33003 total and 94 unique queries that were not parameterized and not expected to be parameterized. The rest of the file lists the unique queries for each of the three types. It can be useful to review all sections to see the queries in use, in case any appear odd and worthy of further review. By default, Sequel::Model does not parameterize model lookups and deletes for scalar primary keys, for performance reasons. Those would show up as missed parameterization. This disables that optimization when running the query parameterization check. Disabling the optimization broke one of the specs, because SequelExtensions#delete did not handle the case where Model#delete called Dataset#delete. Fix it by adding another caller check. Also, only call caller once instead of twice, probably making this faster than it was before. Additionally, I found that logging SQL in any capacity broke about 8 specs that mocked Time.now and expected a specific number of Time.now calls. Such assertions on the number of Time.now calls in the specs are questionable, but work around the issue in this particular case by setting Logger::Time to an object where now returns a static value instead of calling Time.now. While here, fix the rodaauth typo in SequelExtensions#delete.
43 lines
1.2 KiB
Ruby
Executable File
43 lines
1.2 KiB
Ruby
Executable File
#!/usr/local/bin/ruby
|
|
# frozen_string_literal: true
|
|
|
|
parameterized_sql = Hash.new(0)
|
|
other_sql = Hash.new(0)
|
|
|
|
File.open("sql.log").each("\0") do |line|
|
|
if /\AINFO -- : \(\d\.\d*s\) (.*)\0\z/m =~ line
|
|
sql = $1
|
|
|
|
sql, params = sql.split("; [", 2)
|
|
if params || sql.start_with?("PREPARE")
|
|
parameterized_sql[sql] += 1
|
|
else
|
|
other_sql[sql] += 1
|
|
end
|
|
end
|
|
end
|
|
|
|
missed_params, no_expected_params = other_sql.keys.partition do |sql|
|
|
next if sql.match?(/ROLLBACK|BEGIN|SAVEPOINT|LIMIT 0|DEFAULT VALUES|DELETE FROM "[a-z_]*"$|SELECT \* FROM "[a-z_]*"( ORDER BY "[a-z_]*")?$|SELECT count\(\*\) AS "count" FROM'/)
|
|
next unless sql.match?(/SELECT|INSERT|UPDATE|DELETE/)
|
|
|
|
sql.gsub(/LIMIT \d+/, "").gsub(/OFFSET \d+/, "").match?(/[^a-z0-9_][0-9]|'/)
|
|
end
|
|
|
|
print "Summary: "
|
|
print "Missed: #{missed_params.size}|#{missed_params.sum { |s| other_sql[s] }}, "
|
|
print "Parameterized: #{parameterized_sql.size}|#{parameterized_sql.values.sum}, "
|
|
puts "Not Parameterized: #{no_expected_params.size}|#{no_expected_params.sum { |s| other_sql[s] }}"
|
|
puts
|
|
|
|
puts "SQL with missed parameters:"
|
|
puts missed_params.sort
|
|
puts
|
|
|
|
puts "Parameterized SQL:"
|
|
puts parameterized_sql.keys.sort
|
|
puts
|
|
|
|
puts "SQL with no expected parameters:"
|
|
puts no_expected_params.sort
|