Initial commit

This commit is contained in:
Nise Void 2016-10-21 20:01:00 +02:00
commit 358fed43ea
4 changed files with 177 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bindata.go

29
LICENSE Normal file
View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2016, Fuyu
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

55
README.md Normal file
View File

@ -0,0 +1,55 @@
# Go database migrate
This is a simple database migration library for Go. This library is intended to be used with go-bindata.
We recommended using a go generate command to update the go-bindata file.
## Example
`files/0001.sql`:
```sql
CREATE TABLE tests (
Name varchar(100) NOT NULL
);
INSERT INTO tests VALUES ('migration test');
```
Run `go-bindata --prefix files files`
*Optionally add the flags `-nomemcopy` and `-nometadata`*
`main.go`:
```go
package main
import (
"migrate"
)
func main() {
db, err = sql.Open(`postgres`, `host=/run/postgresql dbname=testdb sslmode=disable`)
if err != nil {
fmt.Println(`Failed to connect to database. Message:`, err)
}
err = migrate.Migrate(db, 1, migrate.Options{Schema:`testschema`}, migrations.Asset}
if err != nil {
fmt.Println(`The migration failed! Message:`, err)
}
fmt.Println(`The database migration/update was successful`)
}
```
## File names:
The names of your migration files should look like this:
```
0001.sql
0002.sql
...
0010.sql
...
0325.sql
```

92
migrate.go Normal file
View File

@ -0,0 +1,92 @@
// Package migrate allows you to update your database from your application
package migrate
import (
"database/sql"
"errors"
"fmt"
"strconv"
)
// Options contains all settings
type Options struct {
TableName string // Name used for version info table; defaults to DefaultTableName if not set
Schema string // Schema used for version info table; For PostgreSQL, ignored if not set
AssetPrefix string
}
// DefaultTableName is the name used when no TableName is specified in Options
const DefaultTableName = `version`
// ErrUpdatesMissing indicates an update is missing, making it impossible to execute the migration
var ErrUpdatesMissing = errors.New(`Missing migration files`)
// ErrDatabaseNewer indicates that the database version is newer than the requested version. We throw an error because downgrades might cause dataloss
var ErrDatabaseNewer = errors.New(`Current version is newer than the requested version`)
const fileFormat = `%04d.sql`
// AssetFunc is a function that returns the data for the given name
type AssetFunc func(string) ([]byte, error)
// Migrate executes
func Migrate(db *sql.DB, version int, o Options, asset AssetFunc) error {
if o.TableName == `` {
o.TableName = DefaultTableName
}
table := o.TableName
if o.Schema != `` {
table = o.Schema + `.` + table
}
_, err := db.Exec(`CREATE TABLE IF NOT EXISTS ` + table + ` (Version integer NOT NULL PRIMARY KEY)`)
if err != nil {
return err
}
row := db.QueryRow(`SELECT Version FROM ` + table + ` ORDER BY Version DESC`)
if err != nil {
return err
}
var v int
err = row.Scan(&v)
if err != sql.ErrNoRows && err != nil {
return err
}
if v > version {
return ErrDatabaseNewer
}
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
for i := v + 1; i <= version; i++ {
asset, err := asset(fmt.Sprintf(o.AssetPrefix+fileFormat, version))
if err != nil {
return ErrUpdatesMissing
}
_, err = tx.Exec(string(asset))
if err != nil {
return err
}
_, err = tx.Exec(`INSERT INTO ` + table + ` VALUES (` + strconv.Itoa(i) + `)`)
if err != nil {
return err
}
}
err = tx.Commit()
if err != nil {
return err
}
return nil
}