postgres服务器

时间:2016-06-09 23:58:23

标签: ruby-on-rails postgresql

我遇到的情况是我尝试从特定数据库中删除角色列表,但该角色正在服务器上的多个数据库中使用。

根据the documentation for Dropping Roles,我已按照说明操作:

REASSIGN OWNED BY doomed_role TO successor_role;
DROP OWNED BY doomed_role;
-- repeat the above commands in each database of the cluster
DROP ROLE doomed_role;

文档还说明:

  

因为REASSIGN OWNED [和DROP OWNED]无法访问其他数据库中的对象,所以必须在包含该角色所拥有的对象的每个数据库中运行它。

正如预期的那样,当我运行上述命令时:

conn = ActiveRecord::Base.connection
conn.execute("REASSIGN OWNED BY viewer_role TO postgres")
conn.execute("DROP OWNED BY viewer_role")
conn.execute("DROP ROLE IF EXISTS viewer_role")

我收到错误消息:

ActiveRecord::StatementInvalid: PG::DependentObjectsStillExist:
ERROR: role "viewer_role" cannot be dropped because some objects depend on it
DETAIL:
35 objects in database inst2
35 objects in database inst3
35 objects in database inst4

在rails应用的上下文中,如何为所有数据库调用REASSIGN OWNEDDROP OWNED

我的猜测是我将不得不连接到每个数据库。我找到了一个有效的解决方案:

module DBS
  @@connections = {}

  # get all databases
  conn = ActiveRecord::Base.connection;
  dbs = conn.select_values('SELECT datname FROM pg_database WHERE datistemplate = false')

  # create a connection to each database - this will raise lots and lots of warnings
  dbs.each do |db_name|
    @@connections[db_name] ||=
      begin
        config = ActiveRecord::Base.connection_config
        config = config.merge({database: db_name})

        model = Class.new(ActiveRecord::Base)
        self.const_set("#{db_name.classify}", model) # This is needed as rails raises an error if the class does not have a name :@
        model.establish_connection(config)

        model.connection
      end
  end

  def self.connections
    @@connections
  end
end

roles.each do |role_name|
  DBS.connections.values.each do |conn|
    conn.execute("REASSIGN OWNED BY #{role_name} TO postgres")
    conn.execute("DROP OWNED BY #{role_name}")
  end

  ActiveRecord::Base.connection.execute("DROP ROLE IF EXISTS #{role_name}")
end

但是,仅使用已经建立的ActiveRecord::Base.connection是否可以做同样的事情?

0 个答案:

没有答案