2021-06-01 12:20:20 +00:00
|
|
|
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
|
|
|
|
2019-07-04 11:16:55 +00:00
|
|
|
# NOTE: Why use PG::Connection over ActiveRecord::Base.connection?
|
|
|
|
#
|
|
|
|
# As of Rails 5.2, db:create now runs initializers prior to creating the DB.
|
|
|
|
# That means if an initializer tries to establish an ActiveRecord::Base.connection,
|
|
|
|
# it will raise an ActiveRecord::NoDatabaseError
|
|
|
|
# (see https://github.com/rails/rails/issues/32870 for more details).
|
|
|
|
#
|
|
|
|
# The workaround is to use the bare RDBMS library
|
|
|
|
# and connect to a standard system database instead.
|
|
|
|
|
|
|
|
module Zammad
|
|
|
|
class Application
|
|
|
|
class Initializer
|
2021-06-23 11:35:27 +00:00
|
|
|
module DbPreflightCheck
|
2019-07-04 11:16:55 +00:00
|
|
|
module Postgresql
|
|
|
|
extend Base
|
|
|
|
|
|
|
|
def self.perform
|
|
|
|
check_version_compatibility
|
|
|
|
ensure
|
|
|
|
connection.try(:finish)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.check_version_compatibility
|
2020-06-22 09:57:45 +00:00
|
|
|
return if connection.nil? # Edge case: if Postgres can't find a DB to connect to
|
2019-07-04 11:16:55 +00:00
|
|
|
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.connection
|
|
|
|
alternate_dbs = %w[template0 template1 postgres]
|
|
|
|
|
|
|
|
@connection ||= begin
|
2020-09-30 09:07:01 +00:00
|
|
|
PG.connect(db_config)
|
|
|
|
rescue PG::ConnectionBad
|
|
|
|
db_config[:dbname] = alternate_dbs.pop
|
|
|
|
retry if db_config[:dbname].present?
|
|
|
|
end
|
2019-07-04 11:16:55 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Adapted from ActiveRecord::ConnectionHandling#postgresql_connection
|
|
|
|
def self.db_config
|
|
|
|
@db_config ||= ActiveRecord::Base.connection_config.dup.tap do |config|
|
|
|
|
config.symbolize_keys!
|
|
|
|
config[:user] = config.delete(:username)
|
|
|
|
config[:dbname] = config.delete(:database)
|
|
|
|
config.slice!(*PG::Connection.conndefaults_hash.keys, :requiressl)
|
|
|
|
config.compact!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# formats: "9.5.0"
|
|
|
|
# "10.3 (Debian 10.3-2)"
|
|
|
|
def self.current_version
|
|
|
|
@current_version ||= pg_variable('server_version').split.first
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.min_version
|
|
|
|
@min_version ||= '9.1'
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.vendor
|
|
|
|
@vendor ||= 'PostgreSQL'
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.pg_variable(name)
|
|
|
|
connection.exec("SHOW #{name};").first[name]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|