obfuscated_sql.rb 1.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
module Gitlab
  module Metrics
    # Class for producing SQL queries with sensitive data stripped out.
    class ObfuscatedSQL
      REPLACEMENT = /
        \d+(\.\d+)?      # integers, floats
        | '.+?'          # single quoted strings
        | \/.+?(?<!\\)\/ # regexps (including escaped slashes)
      /x

      MYSQL_REPLACEMENTS = /
        ".+?" # double quoted strings
      /x

      # Regex to replace consecutive placeholders with a single one indicating
      # the length. This can be useful when a "IN" statement uses thousands of
      # IDs (storing this would just be a waste of space).
      CONSECUTIVE = /(\?(\s*,\s*)?){2,}/

      # sql - The raw SQL query as a String.
      def initialize(sql)
        @sql = sql
      end

      # Returns a new, obfuscated SQL query.
      def to_s
        regex = REPLACEMENT

        if Gitlab::Database.mysql?
          regex = Regexp.union(regex, MYSQL_REPLACEMENTS)
        end

        @sql.gsub(regex, '?').gsub(CONSECUTIVE) do |match|
          "#{match.count(',') + 1} values"
        end
      end
    end
  end
end