class Apartment::Adapters::PostgresqlSchemaFromSqlAdapter

Another Adapter for Postgresql when using schemas and SQL

Constants

PSQL_DUMP_BLACKLISTED_STATEMENTS

Public Instance Methods

import_database_schema() click to toggle source
# File lib/apartment/adapters/postgresql_adapter.rb, line 171
def import_database_schema
  preserving_search_path do
    clone_pg_schema
    copy_schema_migrations
  end
end

Private Instance Methods

check_input_against_regexps(input, regexps) click to toggle source

Checks if any of regexps matches against input

# File lib/apartment/adapters/postgresql_adapter.rb, line 277
def check_input_against_regexps(input, regexps)
  regexps.select { |c| input.match c }
end
clone_pg_schema() click to toggle source

Clone default schema into new schema named after current tenant

# File lib/apartment/adapters/postgresql_adapter.rb, line 192
def clone_pg_schema
  pg_schema_sql = patch_search_path(pg_dump_schema)
  Apartment.connection.execute(pg_schema_sql)
end
collect_table_names(models) click to toggle source

Collect table names from AR Models

# File lib/apartment/adapters/postgresql_adapter.rb, line 283
def collect_table_names(models)
  models.map do |m|
    m.constantize.table_name
  end
end
copy_schema_migrations() click to toggle source

Copy data from schema_migrations into new schema

# File lib/apartment/adapters/postgresql_adapter.rb, line 199
def copy_schema_migrations
  pg_migrations_data = patch_search_path(pg_dump_schema_migrations_data)
  Apartment.connection.execute(pg_migrations_data)
end
dbname() click to toggle source

Convenience method for current database name

# File lib/apartment/adapters/postgresql_adapter.rb, line 291
def dbname
  Apartment.connection_config[:database]
end
patch_search_path(sql) click to toggle source

Remove “SET search_path …” line from SQL dump and prepend search_path set to current tenant

@return {String} patched raw SQL dump

# File lib/apartment/adapters/postgresql_adapter.rb, line 255
def patch_search_path(sql)
  search_path = "SET search_path = \"#{current}\", #{default_tenant};"

  swap_schema_qualifier(sql)
    .split("\n")
    .select { |line| check_input_against_regexps(line, PSQL_DUMP_BLACKLISTED_STATEMENTS).empty? }
    .prepend(search_path)
    .join("\n")
end
pg_dump_schema() click to toggle source

Dump postgres default schema

@return {String} raw SQL contaning only postgres schema dump

# File lib/apartment/adapters/postgresql_adapter.rb, line 208
def pg_dump_schema
  # Skip excluded tables? :/
  # excluded_tables =
  #   collect_table_names(Apartment.excluded_models)
  #   .map! {|t| "-T #{t}"}
  #   .join(' ')

  # `pg_dump -s -x -O -n #{default_tenant} #{excluded_tables} #{dbname}`

  with_pg_env { `pg_dump -s -x -O -n #{default_tenant} #{dbname}` }
end
pg_dump_schema_migrations_data() click to toggle source
Dump data from schema_migrations table

@return {String} raw SQL contaning inserts with data from schema_migrations

rubocop:disable Layout/LineLength

# File lib/apartment/adapters/postgresql_adapter.rb, line 225
def pg_dump_schema_migrations_data
  with_pg_env { `pg_dump -a --inserts -t #{default_tenant}.schema_migrations -t #{default_tenant}.ar_internal_metadata #{dbname}` }
end
preserving_search_path() { || ... } click to toggle source

Re-set search path after the schema is imported. Postgres now sets search path to empty before dumping the schema and it mut be reset

# File lib/apartment/adapters/postgresql_adapter.rb, line 184
def preserving_search_path
  search_path = Apartment.connection.execute('show search_path').first['search_path']
  yield
  Apartment.connection.execute("set search_path = #{search_path}")
end
swap_schema_qualifier(sql) click to toggle source
# File lib/apartment/adapters/postgresql_adapter.rb, line 265
def swap_schema_qualifier(sql)
  sql.gsub(/#{default_tenant}\.\w*/) do |match|
    if Apartment.pg_excluded_names.any? { |name| match.include? name }
      match
    else
      match.gsub("#{default_tenant}.", %("#{current}".))
    end
  end
end
with_pg_env() { || ... } click to toggle source

Temporary set Postgresql related environment variables if there are in @config

# File lib/apartment/adapters/postgresql_adapter.rb, line 232
def with_pg_env
  pghost = ENV['PGHOST']
  pgport = ENV['PGPORT']
  pguser = ENV['PGUSER']
  pgpassword = ENV['PGPASSWORD']

  ENV['PGHOST'] = @config[:host] if @config[:host]
  ENV['PGPORT'] = @config[:port].to_s if @config[:port]
  ENV['PGUSER'] = @config[:username].to_s if @config[:username]
  ENV['PGPASSWORD'] = @config[:password].to_s if @config[:password]

  yield
ensure
  ENV['PGHOST'] = pghost
  ENV['PGPORT'] = pgport
  ENV['PGUSER'] = pguser
  ENV['PGPASSWORD'] = pgpassword
end