Skip to content

Commit 343a7d1

Browse files
authored
Merge pull request #7 from ShkrutDenis/develop
Develop
2 parents 6c14617 + 543d75f commit 343a7d1

File tree

8 files changed

+180
-42
lines changed

8 files changed

+180
-42
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,14 @@ Module uses next variables for creating a connection with DB:
4949
- DB_DRIVER
5050
- DB_USER
5151
- DB_PASSWORD
52-
- DB_CONNECTION - format `host:port`
52+
- DB_HOST
53+
- DB_PORT
5354
- DB_NAME
55+
56+
if `DB_HOST` and `DB_PORT` doesn’t exist, will be used a `DB_CONNECTION` with next format: `host:port`
57+
58+
By default, module load env file from the current directory with name `.env`. For use custom env file you can use next flags: `--env-path` and `--env-file`
59+
60+
#### Examples
61+
62+
You can found few examples with create migration in `/examples` repository folder.

db/db.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ func NewConnector() *Connector {
3434
}
3535

3636
func NewConfig() *ConnectionConfig {
37-
var host, port string
38-
connectionParts := strings.Split(os.Getenv("DB_CONNECTION"), ":")
39-
if len(connectionParts) == 2 {
40-
host, port = connectionParts[0], connectionParts[1]
37+
host := os.Getenv("DB_HOST")
38+
port := os.Getenv("DB_PORT")
39+
if host == "" && port == "" {
40+
connectionParts := strings.Split(os.Getenv("DB_CONNECTION"), ":")
41+
if len(connectionParts) == 2 {
42+
host, port = connectionParts[0], connectionParts[1]
43+
}
4144
}
4245

4346
return &ConnectionConfig{

entry.go

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,60 @@
11
package go_migrations
22

33
import (
4+
"flag"
45
"github.com/ShkrutDenis/go-migrations/db"
56
"github.com/ShkrutDenis/go-migrations/model"
67
"github.com/ShkrutDenis/go-migrations/store"
78
"github.com/jmoiron/sqlx"
89
"github.com/joho/godotenv"
910
"log"
11+
"os"
1012
)
1113

1214
var connection *sqlx.DB
13-
var lastBatch int
14-
var firstRun = false
15+
var config *Config
1516

16-
func init() {
17-
err := godotenv.Load()
18-
if err != nil {
19-
log.Println("Error loading .env file")
20-
}
17+
type Config struct {
18+
IsRollback bool
19+
EnvPath string
20+
EnvFile string
2121

22-
connector := db.NewConnector()
23-
connection, err = connector.Connect()
24-
if err != nil {
25-
log.Fatal(err)
22+
lastBatch int
23+
firstRun bool
24+
}
25+
26+
func (c *Config) GetEnvFullPath() string {
27+
if c.EnvPath == "" {
28+
return c.EnvFile
2629
}
30+
_, err := os.Stat(c.EnvPath + "/" + c.EnvFile)
31+
if os.IsNotExist(err) {
32+
return c.EnvPath + "\\" + c.EnvFile
33+
}
34+
return c.EnvPath + "/" + c.EnvFile
35+
}
2736

28-
lastBatch = model.GetLastBatch(connection)
29-
firstRun = model.CreateMigrationsTable(connection)
37+
func init() {
38+
config = &Config{}
3039
}
3140

32-
func Migrate(migs []store.Migratable) {
41+
func Run(migs []store.Migratable) {
42+
parseFlags()
43+
prepare()
44+
45+
if config.IsRollback {
46+
store.RegisterMigrations(migs)
47+
rollBack()
48+
return
49+
}
50+
3351
for _, m := range migs {
3452
upOrIgnore(m)
3553
}
3654
}
3755

38-
func Rollback(migs []store.Migratable) {
39-
store.RegisterMigrations(migs)
40-
rollBack()
41-
}
42-
4356
func rollBack() {
44-
forRollback := model.GetLastMigrations(connection, lastBatch)
57+
forRollback := model.GetLastMigrations(connection, config.lastBatch)
4558
for _, m := range forRollback {
4659
forRun := store.FindMigration(m.Name)
4760
if forRun == nil {
@@ -51,15 +64,40 @@ func rollBack() {
5164
forRun.Down(connection)
5265
log.Println("Rolled back", forRun.GetName())
5366
}
54-
model.RemoveLastBatch(connection, lastBatch)
67+
model.RemoveLastBatch(connection, config.lastBatch)
5568
}
5669

5770
func upOrIgnore(migration store.Migratable) {
58-
if !firstRun && model.MigrationExist(connection, migration.GetName()) {
71+
if !config.firstRun && model.MigrationExist(connection, migration.GetName()) {
5972
return
6073
}
6174
log.Println("Migrating", migration.GetName())
6275
migration.Up(connection)
63-
model.AddMigrationRaw(connection, migration.GetName(), lastBatch+1)
76+
model.AddMigrationRaw(connection, migration.GetName(), config.lastBatch+1)
6477
log.Println("Migrated", migration.GetName())
6578
}
79+
80+
func parseFlags() {
81+
isRollback := flag.Bool("rollback", false, "Flag for init rollback.")
82+
envPath := flag.String("env-path", "", "Path to .env file.")
83+
envFile := flag.String("env-file", ".env", "Env file name.")
84+
flag.Parse()
85+
config.IsRollback = *isRollback
86+
config.EnvPath = *envPath
87+
config.EnvFile = *envFile
88+
}
89+
90+
func prepare() {
91+
err := godotenv.Load(config.GetEnvFullPath())
92+
if err != nil {
93+
log.Println("Error loading .env file")
94+
}
95+
96+
connector := db.NewConnector()
97+
connection, err = connector.Connect()
98+
if err != nil {
99+
log.Fatal(err)
100+
}
101+
config.lastBatch = model.GetLastBatch(connection)
102+
config.firstRun = model.CreateMigrationsTable(connection)
103+
}

examples/change_table.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package list
2+
3+
import (
4+
"github.com/ShkrutDenis/go-migrations/builder"
5+
"github.com/jmoiron/sqlx"
6+
)
7+
8+
type ChangeExampleTable struct {}
9+
10+
func (m *ChangeExampleTable) GetName() string {
11+
// Name of migration.
12+
// It will be stored to DB, must be unique.
13+
return "ChangeExampleTable"
14+
}
15+
16+
func (m *ChangeExampleTable) Up(con *sqlx.DB) {
17+
// Change existed table
18+
table := builder.ChangeTable("example", con)
19+
// For change column, just declare new column and call method Change().
20+
table.String("name", 100).Default("new value").NotNull().Change()
21+
// Remove unique condition
22+
table.Column("email").Type("varchar(50)").NotUnique().Change()
23+
// Add default timestamps (created_at nad updated_at)
24+
table.WithTimestamps()
25+
// Execute queries
26+
table.MustExec()
27+
}
28+
29+
func (m *ChangeExampleTable) Down(con *sqlx.DB) {
30+
table := builder.ChangeTable("example", con)
31+
table.String("name", 100).Nullable().Default("value")
32+
table.Column("email").Type("varchar(50)").Unique()
33+
table.MustExec()
34+
}

examples/create_table.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package list
2+
3+
import (
4+
"github.com/ShkrutDenis/go-migrations/builder"
5+
"github.com/jmoiron/sqlx"
6+
)
7+
8+
type CreateExampleTable struct {}
9+
10+
func (m *CreateExampleTable) GetName() string {
11+
// Name of migration.
12+
// It will be stored to DB, must be unique.
13+
return "CreateExampleTable"
14+
}
15+
16+
func (m *CreateExampleTable) Up(con *sqlx.DB) {
17+
// Create new table
18+
table := builder.NewTable("example", con)
19+
// Add primary key. It will be created column with type int and autoincrement.
20+
table.PrimaryKey("id")
21+
// Nullable column with default value. String(,n) => varchar(n).
22+
table.String("name", 100).Nullable().Default("value")
23+
// Builder has few predefined methods with type declaration.
24+
// Any way, you can use Column().Type() methods for create column with any type.
25+
table.Integer("count").Default("0")
26+
// Unique column
27+
table.Column("email").Type("varchar(50)").Unique()
28+
// Execute queries
29+
table.MustExec()
30+
}
31+
32+
func (m *CreateExampleTable) Down(con *sqlx.DB) {
33+
// Drop table
34+
builder.DropTable("example", con).MustExec()
35+
}

examples/foreign_key.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package list
2+
3+
import (
4+
"github.com/ShkrutDenis/go-migrations/builder"
5+
"github.com/jmoiron/sqlx"
6+
)
7+
8+
type ForeignKeyExampleTable struct {}
9+
10+
func (m *ForeignKeyExampleTable) GetName() string {
11+
// Name of migration.
12+
// It will be stored to DB, must be unique.
13+
return "ForeignKeyExampleTable"
14+
}
15+
16+
func (m *ForeignKeyExampleTable) Up(con *sqlx.DB) {
17+
// Create new table
18+
table := builder.NewTable("fk_example", con)
19+
// Add primary key. It will be created column with type int and autoincrement.
20+
table.PrimaryKey("id")
21+
// Add foreign key. First you need add column then add foreign key.
22+
table.Integer("example_id")
23+
table.ForeignKey("example_id").Reference("example").On("id").OnDelete("cascade").OnUpdate("cascade")
24+
// Execute queries
25+
table.MustExec()
26+
}
27+
28+
func (m *ForeignKeyExampleTable) Down(con *sqlx.DB) {
29+
// Drop table
30+
builder.DropTable("fk_example", con).MustExec()
31+
}

model/migration.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ func RemoveLastBatch(connection *sqlx.DB, lastBatch int) {
5858
connection.MustExec(removeBatchSQL(), lastBatch)
5959
}
6060

61+
// SQL queries functions
6162
func checkTableExitSQL() string {
6263
switch os.Getenv("DB_DRIVER") {
6364
case "mysql":

template/migrations/entry.go

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,13 @@
11
package main
22

33
import (
4-
"flag"
54
gm "github.com/ShkrutDenis/go-migrations"
65
gmStore "github.com/ShkrutDenis/go-migrations/store"
76
"github.com/ShkrutDenis/go-migrations/template/migrations/list"
87
)
98

10-
var isRollback *bool
11-
12-
func init() {
13-
isRollback = flag.Bool("rollback", false, "")
14-
flag.Parse()
15-
}
16-
179
func main() {
18-
if *isRollback {
19-
gm.Rollback(getMigrationsList())
20-
return
21-
}
22-
23-
gm.Migrate(getMigrationsList())
10+
gm.Run(getMigrationsList())
2411
}
2512

2613
func getMigrationsList() []gmStore.Migratable {

0 commit comments

Comments
 (0)