class MaskSQL::Converter
Public Class Methods
new(options)
click to toggle source
# File lib/mask_sql/converter.rb, line 6 def initialize(options) @options = options config = YAML.load_file(options[:config]) @mark = config['mark'] @targets = config['targets'] if options[:insert].nil? && options[:replace].nil? && options[:copy].nil? @options[:insert] = true @options[:replace] = true @options[:copy] = true end @matched_copy = {} end
Public Instance Methods
mask(encoding = nil)
click to toggle source
# File lib/mask_sql/converter.rb, line 22 def mask(encoding = nil) encoding ||= NKF.guess(File.read(@options[:in])).name File.open(@options[:out], "w:#{encoding}") do |out_file| File.open(@options[:in], "r:#{encoding}") do |in_file| in_file.each_line do |line| if @matched_copy.empty? @counters = [] write_line(line, out_file) else write_copy_line(line, out_file) end end end end rescue Encoding::UndefinedConversionError => e raise Encoding::UndefinedConversionError, e.message if encoding == Encoding::UTF_8.name mask(Encoding::UTF_8.name) end
Private Instance Methods
end_string?(value)
click to toggle source
# File lib/mask_sql/converter.rb, line 151 def end_string?(value) value != "'" && value != "('" && value.end_with?("'", "')") end
get_current_count(values, record_index, group_indexes)
click to toggle source
# File lib/mask_sql/converter.rb, line 179 def get_current_count(values, record_index, group_indexes) return record_index if group_indexes.empty? group_values = group_indexes.map do |group_index| values[group_index] end increment_count(group_values) end
get_record_values(all_values, columns)
click to toggle source
# File lib/mask_sql/converter.rb, line 155 def get_record_values(all_values, columns) all_values.each_slice(columns).to_a end
increment_count(group_values)
click to toggle source
# File lib/mask_sql/converter.rb, line 188 def increment_count(group_values) counter = @counters.find do |c| c[:label] == group_values end if counter counter[:count] += 1 else counter = { label: group_values, count: 1 } @counters.push(counter) end counter[:count] end
init_matched_copy(target)
click to toggle source
# File lib/mask_sql/converter.rb, line 67 def init_matched_copy(target) @matched_copy[:dummy_values] = target['dummy_values'] @matched_copy[:group_indexes] = target['group_indexes'] || [] @matched_copy[:record_index] = 1 @counters = [] end
mask_value(masked_value, original_value, mask_index, columns)
click to toggle source
# File lib/mask_sql/converter.rb, line 203 def mask_value(masked_value, original_value, mask_index, columns) masked_value.insert(0, "'") if original_value.start_with?("'", "('") masked_value.insert(-1, "'") if original_value.end_with?("'", "')") masked_value.insert(0, '(') if mask_index.zero? masked_value.insert(-1, ')') if mask_index == columns - 1 masked_value end
mask_values(record_values, target)
click to toggle source
# File lib/mask_sql/converter.rb, line 159 def mask_values(record_values, target) columns = target['columns'] dummy_values = target['dummy_values'] group_indexes = target['group_indexes'] || [] record_values.map!.with_index(1) do |values, record_index| count = get_current_count(values, record_index, group_indexes) dummy_values.each_key do |dummy_index| original_value = values[dummy_index] masked_value = dummy_values[dummy_index].gsub(@mark, count.to_s) values[dummy_index] = mask_value(masked_value, original_value, dummy_index, columns) end values end record_values end
match_copy(line, table)
click to toggle source
# File lib/mask_sql/converter.rb, line 117 def match_copy(line, table) return unless @options[:copy] /^(?<copy_sql>COPY\s*`?#{table}`?.*FROM stdin;)$/i.match(line) end
match_insert(line, table)
click to toggle source
# File lib/mask_sql/converter.rb, line 107 def match_insert(line, table) return unless @options[:insert] /^(?<prefix>INSERT (INTO)?\s*`?#{table}`?.*VALUES\s*)(?<all_values>[^;]+)(?<suffix>;?)$/i.match(line) end
match_line(line, table)
click to toggle source
# File lib/mask_sql/converter.rb, line 94 def match_line(line, table) matched_line = match_insert(line, table) return matched_line if matched_line matched_line = match_replace(line, table) return matched_line if matched_line matched_line = match_copy(line, table) return matched_line if matched_line nil end
match_replace(line, table)
click to toggle source
# File lib/mask_sql/converter.rb, line 112 def match_replace(line, table) return unless @options[:replace] /^(?<prefix>REPLACE (INTO)?\s*`?#{table}`?.*VALUES\s*)(?<all_values>[^;]+)(?<suffix>;?)$/i.match(line) end
parse_all_values(matched_all_values)
click to toggle source
# File lib/mask_sql/converter.rb, line 122 def parse_all_values(matched_all_values) all_values = matched_all_values.chomp.split(',') processing_index = 0 all_values.map!.with_index do |value, index| next if index != 0 && index <= processing_index if start_string?(value) processing_value = value.dup processing_index = index until end_string?(processing_value) processing_index += 1 processing_value += all_values[processing_index] end value = processing_value end value end all_values.compact end
start_string?(value)
click to toggle source
# File lib/mask_sql/converter.rb, line 147 def start_string?(value) value == "'" || value == "('" || (value.start_with?("'", "('") && !value.end_with?("'", "')")) end
write_copy_line(line, output_file)
click to toggle source
# File lib/mask_sql/converter.rb, line 74 def write_copy_line(line, output_file) if /^\\.$/ =~ line output_file.puts line @matched_copy.clear return end record_values = line.split("\t") count = get_current_count(record_values, @matched_copy[:record_index], @matched_copy[:group_indexes]) @matched_copy[:dummy_values].each do |dummy_index, dummy_value| record_values[dummy_index] = dummy_value.sub(/^'/, '') .sub(/'$/, '') .gsub(@mark, count.to_s) end output_file.puts record_values.join("\t") @matched_copy[:record_index] += 1 end
write_line(line, output_file)
click to toggle source
# File lib/mask_sql/converter.rb, line 44 def write_line(line, output_file) @targets.each do |target| matched_line = match_line(line, target['table']) next unless matched_line if matched_line.names.include?('copy_sql') output_file.puts line init_matched_copy(target) return end all_values = parse_all_values(matched_line[:all_values]) record_values = get_record_values(all_values, target['columns']) masked_values = mask_values(record_values, target) output_file.puts "#{matched_line[:prefix]}#{masked_values.join(',')}#{matched_line[:suffix]}" return end output_file.puts line end