mirror of
https://github.com/TECHNOFAB11/dbmate.git
synced 2026-02-02 17:35:08 +01:00
Require presence of up block; optional space after -- (#72)
This commit is contained in:
parent
a31e06b438
commit
02c7bda8a9
3 changed files with 55 additions and 26 deletions
|
|
@ -218,10 +218,9 @@ dbmate supports options passed to a migration block in the form of `key:value` p
|
||||||
```sql
|
```sql
|
||||||
-- migrate:up transaction:false
|
-- migrate:up transaction:false
|
||||||
ALTER TYPE colors ADD VALUE 'orange' AFTER 'red';
|
ALTER TYPE colors ADD VALUE 'orange' AFTER 'red';
|
||||||
ALTER TYPE colors ADD VALUE 'yellow' AFTER 'orange';
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`transaction` will default to `true` for if your database supports it.
|
`transaction` will default to `true` if your database supports it.
|
||||||
|
|
||||||
### Schema File
|
### Schema File
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package dbmate
|
package dbmate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -36,37 +37,33 @@ func parseMigration(path string) (Migration, Migration, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewMigration(), NewMigration(), err
|
return NewMigration(), NewMigration(), err
|
||||||
}
|
}
|
||||||
up, down := parseMigrationContents(string(data))
|
up, down, err := parseMigrationContents(string(data))
|
||||||
return up, down, nil
|
return up, down, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var upRegExp = regexp.MustCompile(`(?m)^-- migrate:up\s+(.+)*$`)
|
var upRegExp = regexp.MustCompile(`(?m)^--\s*migrate:up\s+(.+)*$`)
|
||||||
var downRegExp = regexp.MustCompile(`(?m)^-- migrate:down\s+(.+)*$`)
|
var downRegExp = regexp.MustCompile(`(?m)^--\s*migrate:down\s+(.+)*$`)
|
||||||
|
|
||||||
// parseMigrationContents parses the string contents of a migration.
|
// parseMigrationContents parses the string contents of a migration.
|
||||||
// It will return two Migration objects, the first representing the "up"
|
// It will return two Migration objects, the first representing the "up"
|
||||||
// block and the second representing the "down" block.
|
// block and the second representing the "down" block. This function
|
||||||
//
|
// requires that at least an up block was defined and will otherwise
|
||||||
// Note that with the way this is currently defined, it is possible to
|
// return an error.
|
||||||
// correctly parse a migration that does not define an "up" block or a
|
func parseMigrationContents(contents string) (Migration, Migration, error) {
|
||||||
// "down" block, or one that defines neither. This behavior is, in part,
|
|
||||||
// to preserve backwards compatibility.
|
|
||||||
func parseMigrationContents(contents string) (Migration, Migration) {
|
|
||||||
up := NewMigration()
|
up := NewMigration()
|
||||||
down := NewMigration()
|
down := NewMigration()
|
||||||
|
|
||||||
upMatch := upRegExp.FindStringSubmatchIndex(contents)
|
upMatch := upRegExp.FindStringSubmatchIndex(contents)
|
||||||
downMatch := downRegExp.FindStringSubmatchIndex(contents)
|
downMatch := downRegExp.FindStringSubmatchIndex(contents)
|
||||||
|
|
||||||
|
didNotDefineUpBlock := len(upMatch) == 0
|
||||||
onlyDefinedUpBlock := len(upMatch) != 0 && len(downMatch) == 0
|
onlyDefinedUpBlock := len(upMatch) != 0 && len(downMatch) == 0
|
||||||
onlyDefinedDownBlock := len(upMatch) == 0 && len(downMatch) != 0
|
|
||||||
|
|
||||||
if onlyDefinedUpBlock {
|
if didNotDefineUpBlock {
|
||||||
|
return up, down, fmt.Errorf("dbmate requires each migration to define an up bock with '-- migrate:up'")
|
||||||
|
} else if onlyDefinedUpBlock {
|
||||||
up.Contents = strings.TrimSpace(contents)
|
up.Contents = strings.TrimSpace(contents)
|
||||||
up.Options = parseMigrationOptions(contents, upMatch[2], upMatch[3])
|
up.Options = parseMigrationOptions(contents, upMatch[2], upMatch[3])
|
||||||
} else if onlyDefinedDownBlock {
|
|
||||||
down.Contents = strings.TrimSpace(contents)
|
|
||||||
down.Options = parseMigrationOptions(contents, downMatch[2], downMatch[3])
|
|
||||||
} else {
|
} else {
|
||||||
upStart := upMatch[0]
|
upStart := upMatch[0]
|
||||||
downStart := downMatch[0]
|
downStart := downMatch[0]
|
||||||
|
|
@ -87,7 +84,7 @@ func parseMigrationContents(contents string) (Migration, Migration) {
|
||||||
down.Options = parseMigrationOptions(contents, downMatch[2], downMatch[3])
|
down.Options = parseMigrationOptions(contents, downMatch[2], downMatch[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
return up, down
|
return up, down, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var whitespaceRegExp = regexp.MustCompile(`\s+`)
|
var whitespaceRegExp = regexp.MustCompile(`\s+`)
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseMigrationContents(t *testing.T) {
|
func TestParseMigrationContents(t *testing.T) {
|
||||||
|
// It supports the typical use case.
|
||||||
migration := `-- migrate:up
|
migration := `-- migrate:up
|
||||||
create table users (id serial, name text);
|
create table users (id serial, name text);
|
||||||
-- migrate:down
|
-- migrate:down
|
||||||
drop table users;`
|
drop table users;`
|
||||||
|
|
||||||
up, down := parseMigrationContents(migration)
|
up, down, err := parseMigrationContents(migration)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
require.Equal(t, "-- migrate:up\ncreate table users (id serial, name text);", up.Contents)
|
require.Equal(t, "-- migrate:up\ncreate table users (id serial, name text);", up.Contents)
|
||||||
require.Equal(t, true, up.Options.Transaction())
|
require.Equal(t, true, up.Options.Transaction())
|
||||||
|
|
@ -20,13 +22,33 @@ drop table users;`
|
||||||
require.Equal(t, "-- migrate:down\ndrop table users;", down.Contents)
|
require.Equal(t, "-- migrate:down\ndrop table users;", down.Contents)
|
||||||
require.Equal(t, true, down.Options.Transaction())
|
require.Equal(t, true, down.Options.Transaction())
|
||||||
|
|
||||||
|
// It does not require space between the '--' and 'migrate'
|
||||||
|
migration = `
|
||||||
|
--migrate:up
|
||||||
|
create table users (id serial, name text);
|
||||||
|
|
||||||
|
--migrate:down
|
||||||
|
drop table users;
|
||||||
|
`
|
||||||
|
|
||||||
|
up, down, err = parseMigrationContents(migration)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, "--migrate:up\ncreate table users (id serial, name text);", up.Contents)
|
||||||
|
require.Equal(t, true, up.Options.Transaction())
|
||||||
|
|
||||||
|
require.Equal(t, "--migrate:down\ndrop table users;", down.Contents)
|
||||||
|
require.Equal(t, true, down.Options.Transaction())
|
||||||
|
|
||||||
|
// It is acceptable for down to be defined before up
|
||||||
migration = `-- migrate:down
|
migration = `-- migrate:down
|
||||||
drop table users;
|
drop table users;
|
||||||
-- migrate:up
|
-- migrate:up
|
||||||
create table users (id serial, name text);
|
create table users (id serial, name text);
|
||||||
`
|
`
|
||||||
|
|
||||||
up, down = parseMigrationContents(migration)
|
up, down, err = parseMigrationContents(migration)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
require.Equal(t, "-- migrate:up\ncreate table users (id serial, name text);", up.Contents)
|
require.Equal(t, "-- migrate:up\ncreate table users (id serial, name text);", up.Contents)
|
||||||
require.Equal(t, true, up.Options.Transaction())
|
require.Equal(t, true, up.Options.Transaction())
|
||||||
|
|
@ -34,19 +56,30 @@ create table users (id serial, name text);
|
||||||
require.Equal(t, "-- migrate:down\ndrop table users;", down.Contents)
|
require.Equal(t, "-- migrate:down\ndrop table users;", down.Contents)
|
||||||
require.Equal(t, true, down.Options.Transaction())
|
require.Equal(t, true, down.Options.Transaction())
|
||||||
|
|
||||||
// This migration would not work in Postgres if it were to
|
// It supports turning transactions off for a given migration block,
|
||||||
// run in a transaction, so we would want to disable transactions.
|
// e.g., the below would not work in Postgres inside a transaction.
|
||||||
|
// It also supports omitting the down block.
|
||||||
migration = `-- migrate:up transaction:false
|
migration = `-- migrate:up transaction:false
|
||||||
ALTER TYPE colors ADD VALUE 'orange' AFTER 'red';
|
ALTER TYPE colors ADD VALUE 'orange' AFTER 'red';
|
||||||
ALTER TYPE colors ADD VALUE 'yellow' AFTER 'orange';
|
|
||||||
`
|
`
|
||||||
|
|
||||||
up, down = parseMigrationContents(migration)
|
up, down, err = parseMigrationContents(migration)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
require.Equal(t, "-- migrate:up transaction:false\nALTER TYPE colors ADD VALUE 'orange' AFTER 'red';\nALTER TYPE colors ADD VALUE 'yellow' AFTER 'orange';", up.Contents)
|
require.Equal(t, "-- migrate:up transaction:false\nALTER TYPE colors ADD VALUE 'orange' AFTER 'red';", up.Contents)
|
||||||
require.Equal(t, false, up.Options.Transaction())
|
require.Equal(t, false, up.Options.Transaction())
|
||||||
|
|
||||||
require.Equal(t, "", down.Contents)
|
require.Equal(t, "", down.Contents)
|
||||||
require.Equal(t, true, down.Options.Transaction())
|
require.Equal(t, true, down.Options.Transaction())
|
||||||
|
|
||||||
|
// It does *not* support omitting the up block.
|
||||||
|
migration = `-- drop users table
|
||||||
|
begin;
|
||||||
|
drop table users;
|
||||||
|
commit;
|
||||||
|
`
|
||||||
|
|
||||||
|
_, _, err = parseMigrationContents(migration)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
require.Equal(t, "dbmate requires each migration to define an up bock with '-- migrate:up'", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue