Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot run migrations when postgres extension added in rails 5 application

I want to use pg_trgm extension of Postgres for searching using query

SELECT * FROM USERS WHERE location like '%new%' ORDER BY location DESC;

Since Postgres already don't have pg_trgm I need to execute a command to install it. So my migration to do so is

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

So when I run this migration it is giving me this error:

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

This works if I manually enter to database and execute the command but I need to run it from migration.

like image 693
Rabin Poudyal Avatar asked Sep 10 '17 10:09

Rabin Poudyal


People also ask

How do I run a migration file in rails?

To run a specific migration up or down, use db:migrate:up or db:migrate:down . The version number in the above commands is the numeric prefix in the migration's filename. For example, to migrate to the migration 20160515085959_add_name_to_users. rb , you would use 20160515085959 as the version number.

How does Rails know which migrations to run?

Migration file name format It uses values from the current time for YYYYMMDDHHMMSS and the name of the migration. Once migrations are run, the value YYYYMMDDHHMMSS in migration file, is inserted in a table named schema_migrations .

What does db Migrate do rails?

A Rails migration is a tool for changing an application's database schema. Instead of managing SQL scripts, you define database changes in a domain-specific language (DSL). The code is database-independent, so you can easily move your app to a new platform.


1 Answers

When enabling extensions its a good idea to create a separate migration as it makes it much easier to troubleshoot:

class EnableTrigramIndexLocationExtension < ActiveRecord::Migration[5.1]
  def change
    enable_extension "pg_trgm"
  end
end

Loading an extension requires the same privileges that would be required to create its component objects. For most extensions this means superuser or database owner privileges are needed. The user who runs CREATE EXTENSION becomes the owner of the extension for purposes of later privilege checks, as well as the owner of any objects created by the extension's script.

The simplest way to solve this is by using ALTER ROLE myapp SUPERUSER; which is not a very secure solution but works for development. For a production server you should instead use PostgreSQL Extension Whitelisting.

When generating migrations make sure to use either snakecase or camelcase to make the name readable rails g migration AddTrigramIndexLocationToUsers or rails 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
like image 154
max Avatar answered Oct 23 '22 16:10

max