Skip to content

Commit

Permalink
feat: add error command
Browse files Browse the repository at this point in the history
Closes #17
  • Loading branch information
vladfaust committed Oct 15, 2018
1 parent 421aebd commit 6e75db7
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 9 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,22 @@ migrator.to_latest
migrator.current_version # => 10
```

### Errors

A special command `+migrate error` is available. It raises `Migrate::Migration::Error` when a specific migration file is run. A error can be either top-level or direction-specific. This is useful to point out irreversible migrations:

```sql
-- +migrate up
CREATE TABLE foo;
-- +migrate down
-- +migrate error Could not migrate down from this point
```

```sql
-- +migrate error Could not run this migration file at all
```

### [Cakefile](https://github.com/axvm/cake)

Note that `Cakefile` doesn't support task arguments (that means that `Migrator#to` will not be available). Also see [cake-bake](https://github.com/vladfaust/cake-bake.cr) for baking Cakefiles (this could be helpful in Docker deployments).
Expand Down
43 changes: 43 additions & 0 deletions spec/migrate/migrator_with_errors_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
require "../spec_helper"

db = DB.open(ENV["DATABASE_URL"])

{% for table in %w(foo bar baz) %}
def {{table.id}}_exists?(db)
db.scalar("SELECT COUNT(*) FROM {{table.id}}").as(Int64)
rescue
false
end
{% end %}

describe "Migrate::Migrator with errors" do
drop_db

migrator = Migrate::Migrator.new(
db,
nil,
File.join("spec", "migrations_with_errors")
)

describe "direction-specific errors" do
it do
migrator.up

expect_raises Migrate::Migration::Error do
migrator.down
end

migrator.current_version.should eq 1
end
end

describe "top-level errors" do
it do
expect_raises Migrate::Migration::Error do
migrator.up
end

migrator.current_version.should eq 1
end
end
end
11 changes: 11 additions & 0 deletions spec/migrations_with_errors/1.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- +migrate up
CREATE TABLE foo (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL
);

-- Indexes
CREATE UNIQUE INDEX foo_content_index ON foo (content);

-- +migrate down
-- +migrate error Could not migrate down from version 1
1 change: 1 addition & 0 deletions spec/migrations_with_errors/2.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-- +migrate error Nope
14 changes: 13 additions & 1 deletion src/migrate/migration.cr
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
require "./migration/*"

module Migrate
# :nodoc:
struct Migration
CMD_PREFIX = "-- +migrate"

getter queries_up = Array(String).new, queries_down = Array(String).new
getter error : Exception | Nil, error_up : Exception | Nil, error_down : Exception | Nil

def initialize(lines : Iterator)
direction : Direction? = nil
Expand All @@ -12,12 +15,21 @@ module Migrate

lines.each do |line|
if line.starts_with?(CMD_PREFIX)
cmd = line[CMD_PREFIX.size..-1].strip.downcase
cmd = /^#{Regex.escape(CMD_PREFIX)} (?<cmd>\w+)(?:\s.+)?/.match(line).not_nil!["cmd"].strip.downcase

case cmd
when "up"
direction = Direction::Up
when "down"
direction = Direction::Down
when "error"
message = /^#{Regex.escape(CMD_PREFIX)} error (?<message>.+)$/.match(line).try &.["message"]

case direction
when Direction::Up then @error_up ||= Error.new(message)
when Direction::Down then @error_down ||= Error.new(message)
else @error ||= Error.new(message)
end
else
raise "Unknown command #{cmd}!"
end
Expand Down
7 changes: 7 additions & 0 deletions src/migrate/migration/error.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Migrate
struct Migration
# Could be raised after `error` command. See README for examples.
class Error < Exception
end
end
end
26 changes: 18 additions & 8 deletions src/migrate/migrator.cr
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,30 @@ module Migrate

applied_files.reverse! if direction == Direction::Down

migrations = applied_files.map do |file_path|
migration = Migration.new(File.join(@dir, file_path))
migrations = applied_files.map { |path| Migration.new(File.join(@dir, path)) }

migrations.each do |migration|
if error = migration.error
raise error
end

case direction
when Direction::Up
migration.queries_up
if error = migration.error_up
raise error
end

queries = migration.queries_up
when Direction::Down
migration.queries_down
end.not_nil!
end
if error = migration.error_down
raise error
end

queries = migration.queries_down
end

migrations.each do |migration|
@db.transaction do |tx|
migration.each do |query|
queries.not_nil!.each do |query|
@logger.try &.debug(query)
tx.connection.exec(query)
end
Expand Down

0 comments on commit 6e75db7

Please sign in to comment.