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
# File 'lib/pgbundle/extension.rb', line 14

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

Instance Attribute Details

#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)


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

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



156
157
158
# File 'lib/pgbundle/extension.rb', line 156

def create!(con)
  con.exec create_stmt
end

#create_dependencies(con) ⇒ Object

create the dependency graph on the given connection



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

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



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

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



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

def create_with_dependencies(database)
  return true if created?(database)

  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)


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

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)


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

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



21
22
23
# File 'lib/pgbundle/extension.rb', line 21

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’)



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

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)


99
100
101
# File 'lib/pgbundle/extension.rb', line 99

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:



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

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)


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

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



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

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