class Masker::Adapters::Postgres

Attributes

config[R]
conn[R]
logger[R]

Public Class Methods

new(database_url, config_path, logger, opts = {}) click to toggle source
# File lib/masker/adapters/postgres.rb, line 4
def initialize(database_url, config_path, logger, opts = {})
  @conn = PG.connect(database_url)
  @config = Configurations::Postgres.new(conn, config_path, logger, opts)
  @logger = logger
end

Public Instance Methods

mask() click to toggle source
# File lib/masker/adapters/postgres.rb, line 10
def mask
  remove_temp_tables
  config.remove_missing_tables
  config.remove_missing_columns
  create_temp_tables
  insert_fake_data_into_temp_tables
  merge_tables
  truncate
ensure
  remove_temp_tables
end

Private Instance Methods

create_fake_row(id, columns) click to toggle source
# File lib/masker/adapters/postgres.rb, line 52
def create_fake_row(id, columns)
  columns.map { |_, mask_type| stringify(DataGenerator.generate(mask_type)) }
    .unshift(id)
    .join(", ")
end
create_fake_rows(ids, columns) click to toggle source
# File lib/masker/adapters/postgres.rb, line 48
def create_fake_rows(ids, columns)
  ids.map { |id| "(#{create_fake_row(id, columns)})" }.join(", ")
end
create_temp_tables() click to toggle source
# File lib/masker/adapters/postgres.rb, line 30
def create_temp_tables
  tables.keys.each do |table_name|
    conn.exec("CREATE TABLE temp_#{table_name} AS SELECT * FROM #{table_name} LIMIT 0;")
  end
end
insert_fake_data_into_temp_tables() click to toggle source
# File lib/masker/adapters/postgres.rb, line 36
def insert_fake_data_into_temp_tables
  tables.each do |table, columns|
    logger.info "Masking #{table}..."
    conn.transaction do |conn|
      config.ids_to_mask[table].each_slice(1000) do |ids|
        fake_rows = create_fake_rows(ids, columns)
        conn.exec("INSERT INTO temp_#{table} (id, #{columns.keys.join(", ")}) VALUES #{fake_rows};")
      end
    end
  end
end
merge_tables() click to toggle source
# File lib/masker/adapters/postgres.rb, line 62
def merge_tables
  tables.each do |table, columns|
    set_statement = columns.keys.map { |column| "#{column} = temp_#{table}.#{column}" }.join(", ")
    conn.exec("UPDATE #{table} SET #{set_statement} FROM temp_#{table} WHERE #{table}.id = temp_#{table}.id;")
  end
end
remove_temp_tables() click to toggle source
# File lib/masker/adapters/postgres.rb, line 24
def remove_temp_tables
  tables.keys.each do |table_name|
    conn.exec("DROP TABLE IF EXISTS temp_#{table_name};")
  end
end
stringify(value) click to toggle source
# File lib/masker/adapters/postgres.rb, line 58
def stringify(value)
  value.nil? ? 'NULL' : "'#{conn.escape_string(value.to_s)}'"
end
tables() click to toggle source
# File lib/masker/adapters/postgres.rb, line 76
def tables
  config.tables
end
truncate() click to toggle source
# File lib/masker/adapters/postgres.rb, line 69
def truncate
  config.tables_to_truncate.each do |table|
    logger.info "Truncating #{table}..."
    conn.exec("TRUNCATE #{table};")
  end
end