Module: Sequel::SQLLogNormalizer
- Defined in:
- lib/sequel/extensions/sql_log_normalizer.rb
Class Method Summary collapse
Instance Method Summary collapse
-
#log_connection_yield(sql, conn, args = nil) ⇒ Object
Normalize the SQL before calling super.
-
#normalize_logged_sql(sql) ⇒ Object
Replace literal strings and numbers in SQL with question mark placeholders.
Class Method Details
.extended(db) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/sequel/extensions/sql_log_normalizer.rb', line 33 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 |
Instance Method Details
#log_connection_yield(sql, conn, args = nil) ⇒ Object
Normalize the SQL before calling super.
48 49 50 51 52 53 54 |
# File 'lib/sequel/extensions/sql_log_normalizer.rb', line 48 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) ⇒ Object
Replace literal strings and numbers in SQL with question mark placeholders.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/sequel/extensions/sql_log_normalizer.rb', line 57 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 |