mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
94a3be3e6e
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/1749 Co-authored-by: Aravind K P <8335904+scriptonist@users.noreply.github.com> GitOrigin-RevId: 4515f7f2c58b7f28645b2c5a5d9842aa7a844eae
205 lines
4.4 KiB
Go
205 lines
4.4 KiB
Go
package source
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
)
|
|
|
|
// Direction is either up or down.
|
|
type Direction string
|
|
|
|
const (
|
|
Down Direction = "down"
|
|
Up Direction = "up"
|
|
MetaDown Direction = "metadown"
|
|
MetaUp Direction = "metaup"
|
|
)
|
|
|
|
// Migration is a helper struct for source drivers that need to
|
|
// build the full directory tree in memory.
|
|
// Migration is fully independent from migrate.Migration.
|
|
type Migration struct {
|
|
// Version is the version of this migration.
|
|
Version uint64
|
|
|
|
// Identifier can be any string that helps identifying
|
|
// this migration in the source.
|
|
Identifier string
|
|
|
|
// Direction is either Up or Down.
|
|
Direction Direction
|
|
|
|
// Raw holds the raw location path to this migration in source.
|
|
// ReadUp and ReadDown will use this.
|
|
Raw string
|
|
|
|
// Check if the file exists in a directory
|
|
IsDir bool
|
|
}
|
|
|
|
// Migrations wraps Migration and has an internal index
|
|
// to keep track of Migration order.
|
|
type Migrations struct {
|
|
Index uint64Slice
|
|
Migrations map[uint64]map[Direction]*Migration
|
|
}
|
|
|
|
func NewMigrations() *Migrations {
|
|
return &Migrations{
|
|
Index: make(uint64Slice, 0),
|
|
Migrations: make(map[uint64]map[Direction]*Migration),
|
|
}
|
|
}
|
|
|
|
func (i *Migrations) Append(m *Migration) (err error) {
|
|
if m == nil {
|
|
return fmt.Errorf("migration cannot be nill")
|
|
}
|
|
|
|
if i.Migrations[m.Version] == nil {
|
|
i.Migrations[m.Version] = make(map[Direction]*Migration)
|
|
}
|
|
|
|
// reject duplicate versions
|
|
if migration, dup := i.Migrations[m.Version][m.Direction]; dup {
|
|
return fmt.Errorf("found duplicate migrations for version %d\n- %s\n- %s", m.Version, m.Raw, migration.Raw)
|
|
}
|
|
|
|
i.Migrations[m.Version][m.Direction] = m
|
|
i.buildIndex()
|
|
return nil
|
|
}
|
|
|
|
func (i *Migrations) buildIndex() {
|
|
i.Index = make(uint64Slice, 0)
|
|
for version := range i.Migrations {
|
|
i.Index = append(i.Index, version)
|
|
}
|
|
sort.Sort(i.Index)
|
|
}
|
|
|
|
func (i *Migrations) First() (version uint64, ok bool) {
|
|
if len(i.Index) == 0 {
|
|
return 0, false
|
|
}
|
|
return i.Index[0], true
|
|
}
|
|
|
|
func (i *Migrations) GetLocalVersion() uint64 {
|
|
if len(i.Index) == 0 {
|
|
return 0
|
|
}
|
|
return i.Index[len(i.Index)-1]
|
|
}
|
|
|
|
func (i *Migrations) GetUnappliedMigrations(version uint64) (versions []uint64) {
|
|
if version == 0 {
|
|
return i.Index[0:]
|
|
}
|
|
pos := i.findPos(version)
|
|
if pos >= 0 && len(i.Index) > pos+1 {
|
|
return i.Index[pos+1:]
|
|
}
|
|
return versions
|
|
}
|
|
|
|
func (i *Migrations) Prev(version uint64) (prevVersion uint64, ok bool) {
|
|
pos := i.findPos(version)
|
|
if pos >= 1 && len(i.Index) > pos-1 {
|
|
return i.Index[pos-1], true
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
func (i *Migrations) Next(version uint64) (nextVersion uint64, ok bool) {
|
|
pos := i.findPos(version)
|
|
if pos >= 0 && len(i.Index) > pos+1 {
|
|
return i.Index[pos+1], true
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
func (i *Migrations) GetDirections(version uint64) map[Direction]bool {
|
|
var directions = map[Direction]bool{
|
|
Down: false,
|
|
Up: false,
|
|
MetaDown: false,
|
|
MetaUp: false,
|
|
}
|
|
for k := range i.Migrations[version] {
|
|
directions[k] = true
|
|
}
|
|
return directions
|
|
}
|
|
|
|
func (i *Migrations) Up(version uint64) (m *Migration, ok bool) {
|
|
if _, ok := i.Migrations[version]; ok {
|
|
if mx, ok := i.Migrations[version][Up]; ok {
|
|
return mx, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
func (i *Migrations) MetaUp(version uint64) (m *Migration, ok bool) {
|
|
if _, ok := i.Migrations[version]; ok {
|
|
if mx, ok := i.Migrations[version][MetaUp]; ok {
|
|
return mx, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
func (i *Migrations) Down(version uint64) (m *Migration, ok bool) {
|
|
if _, ok := i.Migrations[version]; ok {
|
|
if mx, ok := i.Migrations[version][Down]; ok {
|
|
return mx, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
func (i *Migrations) MetaDown(version uint64) (m *Migration, ok bool) {
|
|
if _, ok := i.Migrations[version]; ok {
|
|
if mx, ok := i.Migrations[version][MetaDown]; ok {
|
|
return mx, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
func (i *Migrations) ReadName(version uint64) (name string) {
|
|
for k := range i.Migrations[version] {
|
|
return i.Migrations[version][k].Identifier
|
|
}
|
|
return "-"
|
|
}
|
|
|
|
func (i *Migrations) findPos(version uint64) int {
|
|
if len(i.Index) > 0 {
|
|
ix := i.Index.Search(version)
|
|
if ix < len(i.Index) && i.Index[ix] == version {
|
|
return ix
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
type uint64Slice []uint64
|
|
|
|
func (s uint64Slice) Len() int {
|
|
return len(s)
|
|
}
|
|
|
|
func (s uint64Slice) Swap(i, j int) {
|
|
s[i], s[j] = s[j], s[i]
|
|
}
|
|
|
|
func (s uint64Slice) Less(i, j int) bool {
|
|
return s[i] < s[j]
|
|
}
|
|
|
|
func (s uint64Slice) Search(x uint64) int {
|
|
return sort.Search(len(s), func(i int) bool { return s[i] >= x })
|
|
}
|