Class: PgBundle::Extension

Inherits:
Object
  • Object
show all
Defined in:
lib/pgbundle/extension.rb

Overview

The Extension class provides the api for defining an Extension it installation source, and dependencies example:

define an extension named 'foo' at version '0.1.1', with source on github depending on hstore
Extension.new('foo', '0.1.1', github: 'me/foo', requires: 'hstore')
you can then check if the Extension is available on a given database
extension.available?(database)
or install it along with it's dependencies
extension.install(database)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Extension

Returns a new instance of Extension.



14
15
16
17
18
19
20
21
# File 'lib/pgbundle/extension.rb', line 14

def initialize(*args)
  opts = args.last.is_a?(Hash) ? args.pop : {}
  @name, @version = args
  validate(opts)
  self.dependencies = opts[:requires]
  self.flags = opts[:flags]
  set_source(opts)
end

Instance Attribute Details

#flagsObject

Returns the value of attribute flags.



13
14
15
# File 'lib/pgbundle/extension.rb', line 13

def flags
  @flags
end

#nameObject

Returns the value of attribute name.



13
14
15
# File 'lib/pgbundle/extension.rb', line 13

def name
  @name
end

#resolving_dependenciesObject

Returns the value of attribute resolving_dependencies.



13
14
15
# File 'lib/pgbundle/extension.rb', line 13

def resolving_dependencies
  @resolving_dependencies
end

#sourceObject

Returns the value of attribute source.



13
14
15
# File 'lib/pgbundle/extension.rb', line 13

def source
  @source
end

#versionObject

Returns the value of attribute version.



13
14
15
# File 'lib/pgbundle/extension.rb', line 13

def version
  @version
end

Instance Method Details

#available?(database) ⇒ Boolean

returns true if extension is available for installation on a given database

Returns:

  • (Boolean)


60
61
62
63
64
65
66
67
# File 'lib/pgbundle/extension.rb', line 60

def available?(database)
  return false unless installed?(database)
  return true if created?(database)

  created_any_version?(database) ? updatable?(database) : creatable?(database)
  rescue ExtensionCreateError
    false
end

#create!(con) ⇒ Object

create extension on a given database connection



158
159
160
# File 'lib/pgbundle/extension.rb', line 158

def create!(con)
  con.exec create_stmt
end

#create_dependencies(con) ⇒ Object

create the dependency graph on the given connection



147
148
149
150
151
152
153
154
155
# File 'lib/pgbundle/extension.rb', line 147

def create_dependencies(con)
  @resolving_dependencies = true
  dependencies.each do |_, d|
    fail CircularDependencyError.new(name, d.name) if d.resolving_dependencies
    d.create_dependencies(con)
    d.create_or_update!(con)
  end
  @resolving_dependencies = false
end

#create_or_update!(con) ⇒ Object



162
163
164
165
166
167
168
169
170
# File 'lib/pgbundle/extension.rb', line 162

def create_or_update!(con)
  return true if created?(con)
  if created_any_version?(con)
    con.exec update_stmt
  else
    create!(con)
  end
  true
end

#create_with_dependencies(database) ⇒ Object

create the extension along with it’s dependencies in a transaction



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/pgbundle/extension.rb', line 128

def create_with_dependencies(database)
  return true if created?(database)
  return false if database.slave?

  database.transaction do |con|
    begin
      create_dependencies(con)
      create_or_update!(con)
    rescue PG::UndefinedFile => err
      raise ExtensionNotFound.new(name, version)
    rescue PG::UndefinedObject => err
      raise MissingDependency.new(name, err.message)
    end
  end

  true
end

#created?(database_or_connection) ⇒ Boolean

returns true if extension is already created with the correct version in the given database

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/pgbundle/extension.rb', line 70

def created?(database_or_connection)
  if version
    result = database_or_connection.exec("SELECT * FROM pg_available_extension_versions WHERE name ='#{name}' AND version = '#{version}' AND installed").to_a
  else
    result = database_or_connection.exec("SELECT * FROM pg_available_extension_versions WHERE name ='#{name}' AND installed").to_a
  end

  if result.empty?
    false
  else
    true
  end
end

#created_any_version?(database_or_connection) ⇒ Boolean

checks if Extension is already installed at any version thus need ALTER EXTENSION to install

Returns:

  • (Boolean)


175
176
177
178
179
180
181
182
# File 'lib/pgbundle/extension.rb', line 175

def created_any_version?(database_or_connection)
  result = database_or_connection.exec("SELECT * FROM pg_available_extension_versions WHERE name ='#{name}' AND installed").to_a
  if result.empty?
    false
  else
    true
  end
end

#dependenciesObject



23
24
25
# File 'lib/pgbundle/extension.rb', line 23

def dependencies
  @dependencies
end

#dependencies=(obj = nil) ⇒ Object

set dependency hash with different options dependencies= Extension.new(‘foo’), bar: Extension.new(‘bar’)

> => Extension.new(‘foo’), ‘bar’ Extension.new(‘bar’)

dependencies= ‘foo’

> Extension.new(‘foo’)

dependencies= Extension.new(‘foo’)

> Extension.new(‘foo’)

dependencies= [‘foo’, ‘bar’]

> => Extension.new(‘foo’), ‘bar’ Extension.new(‘bar’)



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/pgbundle/extension.rb', line 36

def dependencies=(obj = nil)
  @dependencies = case obj
  when nil
    {}
  when Hash
    Hash[obj.map { |k, v| [k.to_s, v] }]
  when String, Symbol
    { obj.to_s => Extension.new(obj.to_s) }
  when Extension
    { obj.name => obj }
  when Array
    hashable = obj.map do |o|
      case o
      when String, Symbol
        [o.to_s, Extension.new(obj.to_s)]
      when Extension
        [o.name, o]
      end
    end
    Hash[hashable]
  end
end

#dependencies_installed?(database) ⇒ Boolean

checks that all dependencies are installed on a given database

Returns:

  • (Boolean)


101
102
103
# File 'lib/pgbundle/extension.rb', line 101

def dependencies_installed?(database)
  dependencies.all?{|_, d| d.installed?(database)}
end

#install(database, force = false) ⇒ Object

installs extension and all dependencies using make install if optional parameter force is true the extension will be installed even if it’s already there returns true if Extension can successfully be created using CREATE EXTENSION

Raises:



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/pgbundle/extension.rb', line 109

def install(database, force = false)
  unless dependencies.empty?
    install_dependencies(database, force)
  end
  make_install(database, force)
  raise ExtensionNotFound.new(name, version) unless installed?(database)

  add_missing_required_dependencies(database)

  creatable?(database)
end

#installed?(database_or_connection) ⇒ Boolean

returns if the extension is already installed on the database system if it is also already created it returns the installed version

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/pgbundle/extension.rb', line 86

def installed?(database_or_connection)
  if version
    result = database_or_connection.exec("SELECT * FROM pg_available_extension_versions WHERE name ='#{name}' AND version = '#{version}'").to_a
  else
    result = database_or_connection.exec("SELECT * FROM pg_available_extension_versions WHERE name ='#{name}'").to_a
  end

  if result.empty?
    false
  else
    true
  end
end

#uninstall!(database) ⇒ Object

completely removes extension be running make uninstall and DROP EXTENSION



122
123
124
125
# File 'lib/pgbundle/extension.rb', line 122

def uninstall!(database)
  drop_extension(database)
  make_uninstall(database)
end