在 rails 5 应用程序中添加 postgres 扩展时无法运行迁移

Rab*_*yal 5 postgresql ruby-on-rails ruby-on-rails-5

我想使用 Postgres 的 pg_trgm 扩展来使用查询进行搜索

SELECT * FROM USERS WHERE location like '%new%' ORDER BY location DESC;
Run Code Online (Sandbox Code Playgroud)

由于 Postgres 已经没有 pg_trgm 我需要执行一个命令来安装它。所以我这样做的迁移是

class Addtrigramindexlocationtousers < ActiveRecord::Migration[5.1]
  def change
    reversible do |direction|
        direction.up {
            execute %{
                CREATE EXTENSION IF NOT EXISTS pg_trgm;
                CREATE INDEX index_users_trigram_on_location ON users USING gin (location gin_trgm_ops);
            }
        }
        direction.down {
            execute %{
                DROP INDEX index_users_trigram_on_location;
            }           
        }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

因此,当我运行此迁移时,它给了我这个错误:

    ActiveRecord::StatementInvalid: PG::InsufficientPrivilege: ERROR:  permission denied to create extension "pg_trgm"
HINT:  Must be superuser to create this extension.
: 
                DROP INDEX index_users_on_location;
                CREATE EXTENSION IF NOT EXISTS pg_trgm;
                CREATE INDEX index_users_trigram_on_location ON users USING gin (location gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)

如果我手动进入数据库并执行命令,但我需要从迁移中运行它,这会起作用。

max*_*max 6

启用扩展时,最好创建单独的迁移,因为这样可以更轻松地进行故障排除:

class EnableTrigramIndexLocationExtension < ActiveRecord::Migration[5.1]
  def change
    enable_extension "pg_trgm"
  end
end
Run Code Online (Sandbox Code Playgroud)

加载扩展需要与创建其组件对象相同的权限。对于大多数扩展,这意味着需要超级用户或数据库所有者权限。运行 CREATE EXTENSION 的用户将成为扩展的所有者(以便以后进行权限检查),以及扩展的脚本创建的任何对象的所有者。

解决此问题的最简单方法是使用ALTER ROLE myapp SUPERUSER;这不是一个非常安全的解决方案,但适用于开发。对于生产服务器,您应该使用PostgreSQL 扩展白名单

生成迁移时,请确保使用蛇形命名法或驼峰命名法以使名称可读rails g migration AddTrigramIndexLocationToUsersrails g migration add_trigram_index_location_to_users.

class AddTrigramIndexLocationToUsers < ActiveRecord::Migration[5.1]
  def up
    execute %{ 
      CREATE INDEX index_users_trigram_on_location ON users USING gin (location gin_trgm_ops); 
    }
  end

  def down
    remove_index :users, :index_users_trigram_on_location
  end
end
Run Code Online (Sandbox Code Playgroud)