module Sequel::SQLLogNormalizer
Public Class Methods
extended(db)
click to toggle source
# File lib/sequel/extensions/sql_log_normalizer.rb, line 32 def self.extended(db) type = case db.literal("'") when "''''" :standard when "'\\''" :backslash when "N''''" :n_standard else raise Error, "SQL log normalization is not supported on this database (' literalized as #{db.literal("'").inspect})" end db.instance_variable_set(:@sql_string_escape_type, type) end
Public Instance Methods
log_connection_yield(sql, conn, args=nil)
click to toggle source
Normalize the SQL before calling super.
Calls superclass method
# File lib/sequel/extensions/sql_log_normalizer.rb, line 47 def log_connection_yield(sql, conn, args=nil) unless skip_logging? sql = normalize_logged_sql(sql) args = nil end super end
normalize_logged_sql(sql)
click to toggle source
Replace literal strings and numbers in SQL with question mark placeholders.
# File lib/sequel/extensions/sql_log_normalizer.rb, line 56 def normalize_logged_sql(sql) sql = sql.dup sql.force_encoding('BINARY') start_index = 0 check_n = @sql_string_escape_type == :n_standard outside_string = true if @sql_string_escape_type == :backslash search_char = /[\\']/ escape_char_offset = 0 escape_char_value = 92 # backslash else search_char = "'" escape_char_offset = 1 escape_char_value = 39 # apostrophe end # The approach used here goes against Sequel's philosophy of never attempting # to parse SQL. However, parsing the SQL is basically the only way to implement # this support with Sequel's design, and it's better to be pragmatic and accept # this than not be able to support this. # Replace literal strings while outside_string && (index = start_index = sql.index("'", start_index)) if check_n && index != 0 && sql.getbyte(index-1) == 78 # N' start start_index -= 1 end index += 1 outside_string = false while (index = sql.index(search_char, index)) && (sql.getbyte(index + escape_char_offset) == escape_char_value) # skip escaped characters inside string literal index += 2 end if index # Found end of string sql[start_index..index] = '?' start_index += 1 outside_string = true end end # Replace integer and decimal floating point numbers sql.gsub!(/\b-?\d+(?:\.\d+)?\b/, '?') sql end