Class: SchemaEvolutionManager::Db

Inherits:
Object
  • Object
show all
Defined in:
lib/schema-evolution-manager/db.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, opts = {}) ⇒ Db

Returns a new instance of Db.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/schema-evolution-manager/db.rb', line 7

def initialize(url, opts={})
  @url = Preconditions.check_not_blank(url, "url cannot be blank")
  password = opts.delete(:password)

  @psql_executable_with_options = "psql"
  (opts.delete(:set) || []).each do |arg|
    @psql_executable_with_options << " --set #{arg}"
  end

  Preconditions.assert_empty_opts(opts)
  connection_data = ConnectionData.parse_url(@url)

  if password
    ENV['PGPASSFILE'] = Db.password_to_tempfile(connection_data.pgpass(password))
  end
end

Instance Attribute Details

#psql_executable_with_optionsObject (readonly)

Returns the value of attribute psql_executable_with_options.



5
6
7
# File 'lib/schema-evolution-manager/db.rb', line 5

def psql_executable_with_options
  @psql_executable_with_options
end

#urlObject (readonly)

Returns the value of attribute url.



5
6
7
# File 'lib/schema-evolution-manager/db.rb', line 5

def url
  @url
end

Class Method Details

.attribute_values(path) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/schema-evolution-manager/db.rb', line 41

def Db.attribute_values(path)
  Preconditions.assert_class(path, String)

  options = []

  ['quiet', 'no-align', 'tuples-only'].each do |v|
    options << "--#{v}"
  end

  SchemaEvolutionManager::MigrationFile.new(path).attribute_values.map do |value|
    if value.attribute.name == "transaction"
      if value.value == "single"
        options << "--single-transaction"
      elsif value.value == "none"
        # No-op
      else
        raise "File[%s] - attribute[%s] unsupported value[%s]" % [path, value.attribute.name, value.value]
      end
    else
      raise "File[%s] - unsupported attribute named[%s]" % [path, value.attribute.name]
    end
  end

  options
end

.from_args(args, opts = {}) ⇒ Object

Parameters:

  • password:

    Optional password to use when connecting to the database.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/schema-evolution-manager/db.rb', line 108

def Db.from_args(args, opts={})
  Preconditions.assert_class(args, Args)
  password = opts.delete(:password)
  Preconditions.assert_empty_opts(opts)

  options = { :password => password, :set => args.set }
  if args.url
    Db.new(args.url, options)
  else
    base = "%s:%s/%s" % [args.host || "localhost", args.port || ConnectionData::DEFAULT_PORT, args.name]
    url = args.user ? "%s@%s" % [args.user, base] : base
    Db.new("postgres://" + url, options)
  end
end

.parse_command_line_config(arg_string) ⇒ Object

Parses command line arguments returning an instance of Db. Exists if invalid config.



101
102
103
104
105
# File 'lib/schema-evolution-manager/db.rb', line 101

def Db.parse_command_line_config(arg_string)
  Preconditions.assert_class(arg_string, String)
  args = Args.new(arg_string, :optional => ['url', 'host', 'user', 'name', 'port', 'set'])
  Db.from_args(args)
end

.password_to_tempfile(contents) ⇒ Object



128
129
130
131
132
133
# File 'lib/schema-evolution-manager/db.rb', line 128

def Db.password_to_tempfile(contents)
  file = Tempfile.new("sem-db")
  file.write(contents)
  file.rewind
  file.path
end

.schema_nameObject

Returns the name of the schema_evolution_manager schema



124
125
126
# File 'lib/schema-evolution-manager/db.rb', line 124

def Db.schema_name
  "schema_evolution_manager"
end

Instance Method Details

#bootstrap!Object

Installs schema_evolution_manager. Automatically upgrades schema_evolution_manager.



25
26
27
28
29
30
31
32
# File 'lib/schema-evolution-manager/db.rb', line 25

def bootstrap!
  scripts = Scripts.new(self, Scripts::BOOTSTRAP_SCRIPTS)
  dir = File.join(Library.base_dir, "scripts")
  scripts.each_pending(dir) do |filename, path|
    psql_file(filename, path)
    scripts.record_as_run!(filename)
  end
end

#psql_command(sql_command) ⇒ Object

executes a simple sql command.



35
36
37
38
39
# File 'lib/schema-evolution-manager/db.rb', line 35

def psql_command(sql_command)
  Preconditions.assert_class(sql_command, String)
  command = "#{@psql_executable_with_options} --no-align --tuples-only --no-psqlrc --command \"%s\" %s" % [sql_command, @url]
  Library.system_or_error(command)
end

#psql_file(filename, path) ⇒ Object

executes sql commands from a file in a single transaction



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/schema-evolution-manager/db.rb', line 68

def psql_file(filename, path)
  Preconditions.assert_class(path, String)
  Preconditions.check_state(File.exist?(path), "File[%s] not found" % path)

  options = Db.attribute_values(path).join(" ")

  Library.with_temp_file(:prefix => File.basename(path)) do |tmp|
    File.open(tmp, "w") do |out|
      out << "\\set ON_ERROR_STOP true\n\n"
      out << IO.read(path)
    end

    command = "#{@psql_executable_with_options} --file \"%s\" #{options} %s" % [tmp, @url]

    Library.with_temp_file do |output|
      result = `#{command} > #{output} 2>&1`.strip
      status = $?
      if status.to_i > 0
        errors = File.exist?(output) ? IO.read(output) : result
        raise ScriptError.new(self, filename, path, errors)
      end
    end
  end
end

#schema_schema_evolution_manager_exists?Boolean

True if the specific schema exists; false otherwise

Returns:

  • (Boolean)


94
95
96
97
# File 'lib/schema-evolution-manager/db.rb', line 94

def schema_schema_evolution_manager_exists?
  sql = "select count(*) from pg_namespace where nspname='%s'" % Db.schema_name
  psql_command(sql).to_i > 0
end