Skip to content

Commit 83afcc3

Browse files
authored
Add option to create indexes concurrently. Fixes #1124 (#1127)
1 parent 84f6b64 commit 83afcc3

4 files changed

Lines changed: 31 additions & 4 deletions

File tree

spec/avram/migrator/create_index_statement_spec.cr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ describe Avram::Migrator::CreateIndexStatement do
77

88
statement = Avram::Migrator::CreateIndexStatement.new(:users, columns: :email, using: :btree, unique: true).build
99
statement.should eq %(CREATE UNIQUE INDEX users_email_index ON users USING btree ("email");)
10+
11+
statement = Avram::Migrator::CreateIndexStatement.new(:users, columns: :email, using: :btree, concurrently: true).build
12+
statement.should eq %(CREATE INDEX CONCURRENTLY users_email_index ON users USING btree ("email");)
1013
end
1114

1215
it "supports other index types" do

spec/avram/migrator/migration_spec.cr

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ class MigrationCreateAndDropSequences::V994 < Avram::Migrator::Migration::V1
8888
end
8989
end
9090

91+
class MigrationCreateAndDropIndexes::V993 < Avram::Migrator::Migration::V1
92+
def migrate
93+
create_index(:accounts, [:user_id, :number], unique: true, concurrently: true, name: "idx_account_user_id_number")
94+
end
95+
96+
def rollback
97+
drop_index(:accounts, [:user_id, :number], if_exists: true)
98+
end
99+
end
100+
91101
describe Avram::Migrator::Migration::V1 do
92102
it "executes statements in a transaction" do
93103
expect_raises Avram::FailedMigration do
@@ -136,6 +146,18 @@ describe Avram::Migrator::Migration::V1 do
136146
sql.should contain "DROP TRIGGER IF EXISTS trigger_touch_updated_at"
137147
sql.should contain "CREATE TRIGGER trigger_touch_updated_at"
138148
end
149+
150+
it "generates proper SQL for indexes" do
151+
migration = MigrationCreateAndDropIndexes::V993.new
152+
migration.migrate
153+
sql = migration.prepared_statements.join("\n")
154+
155+
sql.should contain %(CREATE UNIQUE INDEX CONCURRENTLY idx_account_user_id_number ON accounts USING btree ("user_id", "number"))
156+
157+
migration.rollback
158+
sql = migration.prepared_statements.join("\n")
159+
sql.should contain %(DROP INDEX IF EXISTS accounts_user_id_number_index)
160+
end
139161
end
140162

141163
describe "if _not_ exists" do

src/avram/migrator/create_index_statement.cr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class Avram::Migrator::CreateIndexStatement
3636
Brin
3737
end
3838

39-
def initialize(@table : TableName, @columns : Columns, using : Symbol = :btree, @unique = false, @name : String? | Symbol? = nil)
39+
def initialize(@table : TableName, @columns : Columns, using : Symbol = :btree, @unique : Bool = false, @concurrently : Bool = false, @name : String? | Symbol? = nil)
4040
@using = IndexTypes.parse?(using.to_s)
4141
raise "index type '#{using}' not supported" if @using.nil?
4242
end
@@ -49,7 +49,9 @@ class Avram::Migrator::CreateIndexStatement
4949
String.build do |index|
5050
index << "CREATE"
5151
index << " UNIQUE" if @unique
52-
index << " INDEX " << index_name
52+
index << " INDEX "
53+
index << "CONCURRENTLY " if @concurrently
54+
index << index_name
5355
index << " ON " << @table
5456
index << " USING " << @using.to_s.downcase
5557
index << " (" << mapped_columns << ");"

src/avram/migrator/statement_helpers.cr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ module Avram::Migrator::StatementHelpers
3636
prepared_statements << DropForeignKeyStatement.new(from, references, column).build
3737
end
3838

39-
def create_index(table_name : TableName, columns : Columns, unique = false, using = :btree, name : String? | Symbol? = nil)
40-
prepared_statements << CreateIndexStatement.new(table_name, columns, using, unique, name).build
39+
def create_index(table_name : TableName, columns : Columns, unique = false, concurrently = false, using = :btree, name : String? | Symbol? = nil)
40+
prepared_statements << CreateIndexStatement.new(table_name, columns, using, unique, concurrently, name).build
4141
end
4242

4343
def drop_index(table_name : TableName, columns : Columns? = nil, if_exists = false, on_delete = :do_nothing, name : String? | Symbol? = nil)

0 commit comments

Comments
 (0)