class PgSync::SchemaSync

Attributes

args[R]
opts[R]

Public Class Methods

new(source:, destination:, tasks:, args:, opts:) click to toggle source
# File lib/pgsync/schema_sync.rb, line 7
def initialize(source:, destination:, tasks:, args:, opts:)
  @source = source
  @destination = destination
  @tasks = tasks
  @args = args
  @opts = opts
end

Public Instance Methods

perform() click to toggle source
# File lib/pgsync/schema_sync.rb, line 15
def perform
  if opts[:preserve]
    raise Error, "Cannot use --preserve with --schema-first or --schema-only"
  end

  # generate commands before starting spinner
  # for better error output if pg_restore not found
  dump_command = dump_command()
  restore_command = restore_command()

  show_spinner = output.tty? && !opts[:debug]

  if show_spinner
    spinner = TTY::Spinner.new(":spinner Syncing schema", format: :dots)
    spinner.auto_spin
  end

  create_schemas if specify_tables?

  # if spinner, capture lines to show on error
  lines = []
  success =
    run_command(dump_command, restore_command) do |line|
      if show_spinner
        lines << line
      else
        log line
      end
    end

  if show_spinner
    if success
      spinner.success
    else
      spinner.error
      log lines.join
    end
  end

  raise Error, "Schema sync returned non-zero exit code" unless success
end

Private Instance Methods

create_schemas() click to toggle source

pg_dump -t won’t create schemas (even with -n) not ideal that this happens outside restore transaction

# File lib/pgsync/schema_sync.rb, line 96
def create_schemas
  schemas = @tasks.map { |t| t.table.schema }.uniq - @destination.schemas
  schemas.sort.each do |schema|
    @destination.create_schema(schema)
  end
end
dump_command() click to toggle source
# File lib/pgsync/schema_sync.rb, line 78
def dump_command
  cmd = ["pg_dump", "-Fc", "--verbose", "--schema-only", "--no-owner", "--no-acl"]
  if specify_tables?
    @tasks.each do |task|
      cmd.concat(["-t", task.quoted_table])
    end
  end
  cmd.concat(["-d", @source.url])
end
restore_command() click to toggle source
# File lib/pgsync/schema_sync.rb, line 88
def restore_command
  cmd = ["pg_restore", "--verbose", "--no-owner", "--no-acl", "--clean"]
  cmd << "--if-exists" if supports_if_exists?
  cmd.concat(["-d", @destination.url])
end
run_command(dump_command, restore_command) { |line| ... } click to toggle source
# File lib/pgsync/schema_sync.rb, line 59
def run_command(dump_command, restore_command)
  err_r, err_w = IO.pipe
  Open3.pipeline_start(dump_command, restore_command, err: err_w) do |wait_thrs|
    err_w.close
    err_r.each do |line|
      yield line
    end
    wait_thrs.all? { |t| t.value.success? }
  end
end
specify_tables?() click to toggle source
# File lib/pgsync/schema_sync.rb, line 103
def specify_tables?
  !opts[:all_schemas] || opts[:tables] || opts[:groups] || args[0] || opts[:exclude] || opts[:schemas]
end
supports_if_exists?() click to toggle source

–if-exists introduced in Postgres 9.4 not ideal, but simpler than trying to parse version

# File lib/pgsync/schema_sync.rb, line 72
def supports_if_exists?
  `pg_restore --help`.include?("--if-exists")
rescue Errno::ENOENT
  raise Error, "pg_restore not found"
end