Refactored, removed old remnants from v0.1.0, documentation added
This commit is contained in:
		
							parent
							
								
									a38bd4304f
								
							
						
					
					
						commit
						d290a67800
					
				
					 2 changed files with 66 additions and 31 deletions
				
			
		
							
								
								
									
										20
									
								
								schema.go
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								schema.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,22 @@
 | 
			
		|||
/*
 | 
			
		||||
Package dbschema is used to keep the SQL schema up to date.
 | 
			
		||||
 | 
			
		||||
	func sqlProvider(dbName string, version int) (sql []byte, found bool) {
 | 
			
		||||
		// read an SQL file and return the contents
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	upgrader := dbschema.NewUpgrader()
 | 
			
		||||
	upgrader.SetSqlCallback(sqlProvider)
 | 
			
		||||
 | 
			
		||||
	if err = upgrader.AddDatabase("127.0.0.1", 5432, "foo", "postgres", "password"); err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = upgrader.Run(); err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
package dbschema
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +27,7 @@ import (
 | 
			
		|||
	"database/sql"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// An upgrader verifies the schema for one or more databases and upgrades them if possible.
 | 
			
		||||
type Upgrader struct {
 | 
			
		||||
	databases map[string]Database
 | 
			
		||||
	logCallback func(string, string)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										77
									
								
								upgrader.go
									
										
									
									
									
								
							
							
						
						
									
										77
									
								
								upgrader.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,9 @@
 | 
			
		|||
package dbschema
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	// External
 | 
			
		||||
	"github.com/lib/pq"
 | 
			
		||||
 | 
			
		||||
	// Standard
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
| 
						 | 
				
			
			@ -9,19 +12,49 @@ import (
 | 
			
		|||
func defaultCallback(topic, msg string) {// {{{
 | 
			
		||||
	fmt.Printf("[%s] %s\n", topic, msg)
 | 
			
		||||
}// }}}
 | 
			
		||||
func NewUpgrader(host string, port int, dbName, user, pass string) (upgrader Upgrader, err error) {// {{{
 | 
			
		||||
 | 
			
		||||
// NewUpgrader creates an upgrader with an empty list of databases.
 | 
			
		||||
func NewUpgrader() (upgrader Upgrader) {// {{{
 | 
			
		||||
	upgrader.logCallback = defaultCallback
 | 
			
		||||
	upgrader.databases = map[string]Database{}
 | 
			
		||||
	return
 | 
			
		||||
}// }}}
 | 
			
		||||
 | 
			
		||||
// SetLogCallback allows to set a callback for custom logging.
 | 
			
		||||
func (upgrader *Upgrader) SetLogCallback(callback func(string, string)) {// {{{
 | 
			
		||||
	upgrader.logCallback = callback
 | 
			
		||||
}// }}}
 | 
			
		||||
// SetSqlCallback is required for providing the SQL schema updates.
 | 
			
		||||
func (upgrader *Upgrader) SetSqlCallback(callback func(string, int) ([]byte, bool)) {// {{{
 | 
			
		||||
	upgrader.sqlCallback = callback
 | 
			
		||||
}// }}}
 | 
			
		||||
 | 
			
		||||
func (dbase Database) createSchemaTable() (err error) {// {{{
 | 
			
		||||
	dbase.upgrader.logCallback("create", fmt.Sprintf("%s, _db.schema", dbase.DbName))
 | 
			
		||||
	_, err = dbase.db.Exec(`CREATE SCHEMA "_db"`)
 | 
			
		||||
 | 
			
		||||
	// Error code 42P06 "duplicate_schema" is an OK error,
 | 
			
		||||
	// table can still be missing and created.
 | 
			
		||||
	pqErr, _ := err.(*pq.Error)
 | 
			
		||||
	if pqErr != nil && pqErr.Code != "42P06" {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = dbase.db.Exec(`
 | 
			
		||||
		CREATE TABLE "_db"."schema" (
 | 
			
		||||
			version  int4      NOT NULL,
 | 
			
		||||
			updated  timestamp NOT NULL DEFAULT NOW(),
 | 
			
		||||
 | 
			
		||||
			CONSTRAINT schema_pk PRIMARY KEY (version)
 | 
			
		||||
		)`,
 | 
			
		||||
	)
 | 
			
		||||
	return
 | 
			
		||||
}// }}}
 | 
			
		||||
func (dbase Database) appendSchemaVersion(version int) (err error) {// {{{
 | 
			
		||||
	_, err = dbase.db.Exec(`INSERT INTO _db.schema(version) VALUES($1)`, version)
 | 
			
		||||
	return
 | 
			
		||||
}// }}}
 | 
			
		||||
 | 
			
		||||
func (dbase Database) verifySchemaTable() (err error) {// {{{
 | 
			
		||||
	var rows *sql.Rows
 | 
			
		||||
	if rows, err = dbase.db.Query(
 | 
			
		||||
| 
						 | 
				
			
			@ -41,37 +74,21 @@ func (dbase Database) verifySchemaTable() (err error) {// {{{
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !exists {
 | 
			
		||||
		dbase.upgrader.logCallback("create", fmt.Sprintf("%s, _db.schema", dbase.DbName))
 | 
			
		||||
		dbase.db.Exec(`CREATE SCHEMA "_db"`)
 | 
			
		||||
 | 
			
		||||
		if _, err = dbase.db.Exec(`
 | 
			
		||||
			CREATE TABLE "_db"."schema" (
 | 
			
		||||
				version  int4      NOT NULL,
 | 
			
		||||
				updated  timestamp NOT NULL DEFAULT NOW(),
 | 
			
		||||
 | 
			
		||||
				CONSTRAINT schema_pk PRIMARY KEY (version)
 | 
			
		||||
			)`,
 | 
			
		||||
		); err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	if exists {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	err = dbase.createSchemaTable()
 | 
			
		||||
	return
 | 
			
		||||
}// }}}
 | 
			
		||||
func (dbase Database) verifySchemaEntry() (err error) {// {{{
 | 
			
		||||
	var rows *sql.Rows
 | 
			
		||||
	rows, err = dbase.db.Query(`SELECT version FROM _db.schema LIMIT 1`)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
	var version int
 | 
			
		||||
	var row *sql.Row
 | 
			
		||||
	row = dbase.db.QueryRow(`SELECT version FROM _db.schema LIMIT 1`)
 | 
			
		||||
 | 
			
		||||
	if !rows.Next() {
 | 
			
		||||
	err = row.Scan(&version)
 | 
			
		||||
	if err == sql.ErrNoRows {
 | 
			
		||||
		dbase.upgrader.logCallback("initiate version", dbase.DbName)
 | 
			
		||||
		_, err = dbase.db.Exec(`INSERT INTO _db.schema(version) VALUES(0)`)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		err = dbase.appendSchemaVersion(0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +111,7 @@ func (dbase Database) version() (version int, err error) {// {{{
 | 
			
		|||
	return
 | 
			
		||||
}// }}}
 | 
			
		||||
 | 
			
		||||
// AddDatabase sets a database up for the Run() function with verifying/creating the _db.schema table.
 | 
			
		||||
func (upgrader Upgrader) AddDatabase(host string, port int, dbName, user, pass string) (err error) {// {{{
 | 
			
		||||
	var db Database
 | 
			
		||||
	if db, err = newDatabase(host, port, dbName, user, pass); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +128,7 @@ func (upgrader Upgrader) AddDatabase(host string, port int, dbName, user, pass s
 | 
			
		|||
	err = db.verifySchemaEntry()
 | 
			
		||||
	return
 | 
			
		||||
}// }}}
 | 
			
		||||
// Run executes the actual schema updates until there are no more available.
 | 
			
		||||
func (upgrader Upgrader) Run() (err error) {// {{{
 | 
			
		||||
	var version int
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -131,11 +150,7 @@ func (upgrader Upgrader) Run() (err error) {// {{{
 | 
			
		|||
			if _, err = dbase.db.Exec(string(sql)); err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			_, err = dbase.db.Exec(`
 | 
			
		||||
				INSERT INTO _db.schema(version)
 | 
			
		||||
				VALUES($1)
 | 
			
		||||
			`, version)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
			if err = dbase.appendSchemaVersion(version); err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue