class Squcumber::Postgres::Mock::Database

Constants

DELETE_DB_WHEN_FINISHED
TEST_DB_NAME_OVERRIDE

Public Class Methods

new(production_database) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 10
def initialize(production_database)
  @production_database = production_database or raise ArgumentError, 'No production database provided'

  test_db_name_postfix = TEST_DB_NAME_OVERRIDE.empty? ? rand(10000..99999) : TEST_DB_NAME_OVERRIDE
  @test_db_name = "test_env_#{test_db_name_postfix}"

  if @production_database.exec("select datname from pg_database where datname like '%#{@test_db_name}%'").num_tuples != 0
    @production_database.exec("drop database #{@test_db_name}")
  end
  @production_database.exec("create database #{@test_db_name}")

  @testing_database = PG.connect(
    host: ENV['DB_HOST'],
    port: ENV['DB_PORT'],
    dbname: @test_db_name,
    user: ENV['DB_USER'],
    password: ENV['DB_PASSWORD']
  )
end

Public Instance Methods

copy_table_def_from_prod(schema, table) click to toggle source

Redshift does not allow to copy a table schema to another database, i.e. `create table some_db.some_table (like another_db.some_table)` cannot be used.

# File lib/squcumber-postgres/mock/database.rb, line 56
def copy_table_def_from_prod(schema, table)
  create_table_statement = _get_create_table_statement(schema, table)
  exec(create_table_statement)
end
copy_table_defs_from_prod(tables) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 61
def copy_table_defs_from_prod(tables)
  tables.each do |obj|
    obj.each { |schema, table| copy_table_def_from_prod(schema, table) }
  end
end
destroy() click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 87
def destroy
  @testing_database.close()

  if DELETE_DB_WHEN_FINISHED
    attempts = 0
    begin
      attempts += 1
      @production_database.exec("drop database #{@test_db_name}")
    rescue PG::ObjectInUse
      sleep 5
      retry unless attempts >= 3
    end
  else
    puts "\nTest database has been kept alive: #{@test_db_name}"
  end

  @production_database.close()
end
exec(statement) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 44
def exec(statement)
  @testing_database.exec(statement)
end
Also aliased as: query
exec_file(path) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 49
def exec_file(path)
  exec(File.read("#{path}"))
end
Also aliased as: query_file
insert_mock_values(schema_and_table, mock) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 74
def insert_mock_values(schema_and_table, mock)
  schema, table = schema_and_table.split('.')
  keys = []
  vals = []
  mock.each do |key, value|
    unless value.nil?
      keys << key
      vals << (value.is_a?(String) ? "'#{value}'" : value)
    end
  end
  exec("insert into #{schema}.#{table} (#{keys.join(',')}) values (#{vals.join(',')})") unless vals.empty?
end
mock(mock) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 67
def mock(mock)
  mock.each do |schema_and_table, data|
    raise "Mock data for #{schema_and_table} is not correctly formatted: must be Array but was #{data.class}" unless data.is_a?(Array)
    data.each { |datum| insert_mock_values(schema_and_table, datum) }
  end
end
query(statement)
Alias for: exec
query_file(path)
Alias for: exec_file
setup(schemas) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 30
def setup(schemas)
  schemas.each do |schema|
    exec("drop schema if exists #{schema} cascade")
    exec("create schema #{schema}")
  end
end
truncate_all_tables() click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 37
def truncate_all_tables
  @testing_database
    .exec("select schemaname || '.' || tablename as schema_and_table from pg_tables where tableowner = '#{ENV['DB_USER']}'")
    .map { |row| row['schema_and_table'] }
    .each { |schema_and_table| exec("truncate table #{schema_and_table}") }
end

Private Instance Methods

_get_column_definitions(table_definition) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 118
def _get_column_definitions(table_definition)
  table_definition.map do |definition|
    schema_column_type = ''
    is_array = false
    if definition['data_type'].eql?('ARRAY')
        is_array = true
        schema_column_type = definition['udt_name'].gsub(/^\_/, '')
    else
        schema_column_type = definition['data_type']
    end

    # Deal with (var)chars
    if definition['character_maximum_length']
        schema_column_type = schema_column_type + "(#{definition['character_maximum_length'].to_s})"
    end

    # Deal with decimals
    if definition['udt_name'].eql?('numeric') and definition['numeric_precision'] and definition['numeric_scale']
        schema_column_type = schema_column_type + "(#{definition['numeric_precision'].to_s},#{definition['numeric_scale'].to_s})"
    end

    # Deal with arrays
    if is_array
        schema_column_type = schema_column_type + '[]'
    end

    "#{definition['column_name']} #{schema_column_type} default null"
  end
end
_get_create_table_statement(schema, table) click to toggle source
# File lib/squcumber-postgres/mock/database.rb, line 108
def _get_create_table_statement(schema, table)
  @production_database.exec("set search_path to '$user', #{schema};")
  table_schema = @production_database.query("select * from information_schema.columns where table_schema = '#{schema}' and table_name = '#{table}';")
  raise "Sorry, there is no table information for #{schema}.#{table}" if table_schema.num_tuples == 0

  definitions = _get_column_definitions(table_schema).join(',')

  "create table if not exists #{schema}.#{table} (#{definitions});"
end