summaryrefslogtreecommitdiff
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/uptrace/bun/migrate/migration.go272
-rw-r--r--vendor/github.com/uptrace/bun/migrate/migrations.go168
-rw-r--r--vendor/github.com/uptrace/bun/migrate/migrator.go401
3 files changed, 841 insertions, 0 deletions
diff --git a/vendor/github.com/uptrace/bun/migrate/migration.go b/vendor/github.com/uptrace/bun/migrate/migration.go
new file mode 100644
index 000000000..79f13f972
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/migrate/migration.go
@@ -0,0 +1,272 @@
+package migrate
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "fmt"
+ "io/fs"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/uptrace/bun"
+)
+
+type Migration struct {
+ bun.BaseModel
+
+ ID int64
+ Name string
+ GroupID int64
+ MigratedAt time.Time `bun:",notnull,nullzero,default:current_timestamp"`
+
+ Up MigrationFunc `bun:"-"`
+ Down MigrationFunc `bun:"-"`
+}
+
+func (m *Migration) String() string {
+ return m.Name
+}
+
+func (m *Migration) IsApplied() bool {
+ return m.ID > 0
+}
+
+type MigrationFunc func(ctx context.Context, db *bun.DB) error
+
+func NewSQLMigrationFunc(fsys fs.FS, name string) MigrationFunc {
+ return func(ctx context.Context, db *bun.DB) error {
+ isTx := strings.HasSuffix(name, ".tx.up.sql") || strings.HasSuffix(name, ".tx.down.sql")
+
+ f, err := fsys.Open(name)
+ if err != nil {
+ return err
+ }
+
+ scanner := bufio.NewScanner(f)
+ var queries []string
+
+ var query []byte
+ for scanner.Scan() {
+ b := scanner.Bytes()
+
+ const prefix = "--bun:"
+ if bytes.HasPrefix(b, []byte(prefix)) {
+ b = b[len(prefix):]
+ if bytes.Equal(b, []byte("split")) {
+ queries = append(queries, string(query))
+ query = query[:0]
+ continue
+ }
+ return fmt.Errorf("bun: unknown directive: %q", b)
+ }
+
+ query = append(query, b...)
+ query = append(query, '\n')
+ }
+
+ if len(query) > 0 {
+ queries = append(queries, string(query))
+ }
+ if err := scanner.Err(); err != nil {
+ return err
+ }
+
+ var idb bun.IConn
+
+ if isTx {
+ tx, err := db.BeginTx(ctx, nil)
+ if err != nil {
+ return err
+ }
+ idb = tx
+ } else {
+ conn, err := db.Conn(ctx)
+ if err != nil {
+ return err
+ }
+ idb = conn
+ }
+
+ for _, q := range queries {
+ _, err = idb.ExecContext(ctx, q)
+ if err != nil {
+ return err
+ }
+ }
+
+ if tx, ok := idb.(bun.Tx); ok {
+ return tx.Commit()
+ } else if conn, ok := idb.(bun.Conn); ok {
+ return conn.Close()
+ }
+
+ panic("not reached")
+ }
+}
+
+const goTemplate = `package %s
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
+ fmt.Print(" [up migration] ")
+ return nil
+ }, func(ctx context.Context, db *bun.DB) error {
+ fmt.Print(" [down migration] ")
+ return nil
+ })
+}
+`
+
+const sqlTemplate = `SELECT 1
+
+--bun:split
+
+SELECT 2
+`
+
+//------------------------------------------------------------------------------
+
+type MigrationSlice []Migration
+
+func (ms MigrationSlice) String() string {
+ if len(ms) == 0 {
+ return "empty"
+ }
+
+ if len(ms) > 5 {
+ return fmt.Sprintf("%d migrations (%s ... %s)", len(ms), ms[0].Name, ms[len(ms)-1].Name)
+ }
+
+ var sb strings.Builder
+
+ for i := range ms {
+ if i > 0 {
+ sb.WriteString(", ")
+ }
+ sb.WriteString(ms[i].Name)
+ }
+
+ return sb.String()
+}
+
+// Applied returns applied migrations in descending order
+// (the order is important and is used in Rollback).
+func (ms MigrationSlice) Applied() MigrationSlice {
+ var applied MigrationSlice
+ for i := range ms {
+ if ms[i].IsApplied() {
+ applied = append(applied, ms[i])
+ }
+ }
+ sortDesc(applied)
+ return applied
+}
+
+// Unapplied returns unapplied migrations in ascending order
+// (the order is important and is used in Migrate).
+func (ms MigrationSlice) Unapplied() MigrationSlice {
+ var unapplied MigrationSlice
+ for i := range ms {
+ if !ms[i].IsApplied() {
+ unapplied = append(unapplied, ms[i])
+ }
+ }
+ sortAsc(unapplied)
+ return unapplied
+}
+
+// LastGroupID returns the last applied migration group id.
+// The id is 0 when there are no migration groups.
+func (ms MigrationSlice) LastGroupID() int64 {
+ var lastGroupID int64
+ for i := range ms {
+ groupID := ms[i].GroupID
+ if groupID != 0 && groupID > lastGroupID {
+ lastGroupID = groupID
+ }
+ }
+ return lastGroupID
+}
+
+// LastGroup returns the last applied migration group.
+func (ms MigrationSlice) LastGroup() *MigrationGroup {
+ group := &MigrationGroup{
+ ID: ms.LastGroupID(),
+ }
+ if group.ID == 0 {
+ return group
+ }
+ for i := range ms {
+ if ms[i].GroupID == group.ID {
+ group.Migrations = append(group.Migrations, ms[i])
+ }
+ }
+ return group
+}
+
+type MigrationGroup struct {
+ ID int64
+ Migrations MigrationSlice
+}
+
+func (g *MigrationGroup) IsZero() bool {
+ return g.ID == 0 && len(g.Migrations) == 0
+}
+
+func (g *MigrationGroup) String() string {
+ if g.IsZero() {
+ return "nil"
+ }
+ return fmt.Sprintf("group #%d (%s)", g.ID, g.Migrations)
+}
+
+type MigrationFile struct {
+ Name string
+ Path string
+ Content string
+}
+
+//------------------------------------------------------------------------------
+
+type migrationConfig struct {
+ nop bool
+}
+
+func newMigrationConfig(opts []MigrationOption) *migrationConfig {
+ cfg := new(migrationConfig)
+ for _, opt := range opts {
+ opt(cfg)
+ }
+ return cfg
+}
+
+type MigrationOption func(cfg *migrationConfig)
+
+func WithNopMigration() MigrationOption {
+ return func(cfg *migrationConfig) {
+ cfg.nop = true
+ }
+}
+
+//------------------------------------------------------------------------------
+
+func sortAsc(ms MigrationSlice) {
+ sort.Slice(ms, func(i, j int) bool {
+ return ms[i].Name < ms[j].Name
+ })
+}
+
+func sortDesc(ms MigrationSlice) {
+ sort.Slice(ms, func(i, j int) bool {
+ return ms[i].Name > ms[j].Name
+ })
+}
diff --git a/vendor/github.com/uptrace/bun/migrate/migrations.go b/vendor/github.com/uptrace/bun/migrate/migrations.go
new file mode 100644
index 000000000..9af861048
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/migrate/migrations.go
@@ -0,0 +1,168 @@
+package migrate
+
+import (
+ "errors"
+ "fmt"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "strings"
+)
+
+type MigrationsOption func(m *Migrations)
+
+func WithMigrationsDirectory(directory string) MigrationsOption {
+ return func(m *Migrations) {
+ m.explicitDirectory = directory
+ }
+}
+
+type Migrations struct {
+ ms MigrationSlice
+
+ explicitDirectory string
+ implicitDirectory string
+}
+
+func NewMigrations(opts ...MigrationsOption) *Migrations {
+ m := new(Migrations)
+ for _, opt := range opts {
+ opt(m)
+ }
+ m.implicitDirectory = filepath.Dir(migrationFile())
+ return m
+}
+
+func (m *Migrations) Sorted() MigrationSlice {
+ migrations := make(MigrationSlice, len(m.ms))
+ copy(migrations, m.ms)
+ sortAsc(migrations)
+ return migrations
+}
+
+func (m *Migrations) MustRegister(up, down MigrationFunc) {
+ if err := m.Register(up, down); err != nil {
+ panic(err)
+ }
+}
+
+func (m *Migrations) Register(up, down MigrationFunc) error {
+ fpath := migrationFile()
+ name, err := extractMigrationName(fpath)
+ if err != nil {
+ return err
+ }
+
+ m.Add(Migration{
+ Name: name,
+ Up: up,
+ Down: down,
+ })
+
+ return nil
+}
+
+func (m *Migrations) Add(migration Migration) {
+ if migration.Name == "" {
+ panic("migration name is required")
+ }
+ m.ms = append(m.ms, migration)
+}
+
+func (m *Migrations) DiscoverCaller() error {
+ dir := filepath.Dir(migrationFile())
+ return m.Discover(os.DirFS(dir))
+}
+
+func (m *Migrations) Discover(fsys fs.FS) error {
+ return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ if d.IsDir() {
+ return nil
+ }
+
+ if !strings.HasSuffix(path, ".up.sql") && !strings.HasSuffix(path, ".down.sql") {
+ return nil
+ }
+
+ name, err := extractMigrationName(path)
+ if err != nil {
+ return err
+ }
+
+ migration := m.getOrCreateMigration(name)
+ if err != nil {
+ return err
+ }
+ migrationFunc := NewSQLMigrationFunc(fsys, path)
+
+ if strings.HasSuffix(path, ".up.sql") {
+ migration.Up = migrationFunc
+ return nil
+ }
+ if strings.HasSuffix(path, ".down.sql") {
+ migration.Down = migrationFunc
+ return nil
+ }
+
+ return errors.New("migrate: not reached")
+ })
+}
+
+func (m *Migrations) getOrCreateMigration(name string) *Migration {
+ for i := range m.ms {
+ m := &m.ms[i]
+ if m.Name == name {
+ return m
+ }
+ }
+
+ m.ms = append(m.ms, Migration{Name: name})
+ return &m.ms[len(m.ms)-1]
+}
+
+func (m *Migrations) getDirectory() string {
+ if m.explicitDirectory != "" {
+ return m.explicitDirectory
+ }
+ if m.implicitDirectory != "" {
+ return m.implicitDirectory
+ }
+ return filepath.Dir(migrationFile())
+}
+
+func migrationFile() string {
+ const depth = 32
+ var pcs [depth]uintptr
+ n := runtime.Callers(1, pcs[:])
+ frames := runtime.CallersFrames(pcs[:n])
+
+ for {
+ f, ok := frames.Next()
+ if !ok {
+ break
+ }
+ if !strings.Contains(f.Function, "/bun/migrate.") {
+ return f.File
+ }
+ }
+
+ return ""
+}
+
+var fnameRE = regexp.MustCompile(`^(\d{14})_[0-9a-z_\-]+\.`)
+
+func extractMigrationName(fpath string) (string, error) {
+ fname := filepath.Base(fpath)
+
+ matches := fnameRE.FindStringSubmatch(fname)
+ if matches == nil {
+ return "", fmt.Errorf("migrate: unsupported migration name format: %q", fname)
+ }
+
+ return matches[1], nil
+}
diff --git a/vendor/github.com/uptrace/bun/migrate/migrator.go b/vendor/github.com/uptrace/bun/migrate/migrator.go
new file mode 100644
index 000000000..f9b4a51c2
--- /dev/null
+++ b/vendor/github.com/uptrace/bun/migrate/migrator.go
@@ -0,0 +1,401 @@
+package migrate
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "path/filepath"
+ "regexp"
+ "time"
+
+ "github.com/uptrace/bun"
+)
+
+type MigratorOption func(m *Migrator)
+
+func WithTableName(table string) MigratorOption {
+ return func(m *Migrator) {
+ m.table = table
+ }
+}
+
+func WithLocksTableName(table string) MigratorOption {
+ return func(m *Migrator) {
+ m.locksTable = table
+ }
+}
+
+type Migrator struct {
+ db *bun.DB
+ migrations *Migrations
+
+ ms MigrationSlice
+
+ table string
+ locksTable string
+}
+
+func NewMigrator(db *bun.DB, migrations *Migrations, opts ...MigratorOption) *Migrator {
+ m := &Migrator{
+ db: db,
+ migrations: migrations,
+
+ ms: migrations.ms,
+
+ table: "bun_migrations",
+ locksTable: "bun_migration_locks",
+ }
+ for _, opt := range opts {
+ opt(m)
+ }
+ return m
+}
+
+func (m *Migrator) DB() *bun.DB {
+ return m.db
+}
+
+// MigrationsWithStatus returns migrations with status in ascending order.
+func (m *Migrator) MigrationsWithStatus(ctx context.Context) (MigrationSlice, error) {
+ sorted := m.migrations.Sorted()
+
+ applied, err := m.selectAppliedMigrations(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ appliedMap := migrationMap(applied)
+ for i := range sorted {
+ m1 := &sorted[i]
+ if m2, ok := appliedMap[m1.Name]; ok {
+ m1.ID = m2.ID
+ m1.GroupID = m2.GroupID
+ m1.MigratedAt = m2.MigratedAt
+ }
+ }
+
+ return sorted, nil
+}
+
+func (m *Migrator) Init(ctx context.Context) error {
+ if _, err := m.db.NewCreateTable().
+ Model((*Migration)(nil)).
+ ModelTableExpr(m.table).
+ IfNotExists().
+ Exec(ctx); err != nil {
+ return err
+ }
+ if _, err := m.db.NewCreateTable().
+ Model((*migrationLock)(nil)).
+ ModelTableExpr(m.locksTable).
+ IfNotExists().
+ Exec(ctx); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (m *Migrator) Reset(ctx context.Context) error {
+ if _, err := m.db.NewDropTable().
+ Model((*Migration)(nil)).
+ ModelTableExpr(m.table).
+ IfExists().
+ Exec(ctx); err != nil {
+ return err
+ }
+ if _, err := m.db.NewDropTable().
+ Model((*migrationLock)(nil)).
+ ModelTableExpr(m.locksTable).
+ IfExists().
+ Exec(ctx); err != nil {
+ return err
+ }
+ return m.Init(ctx)
+}
+
+func (m *Migrator) Migrate(ctx context.Context, opts ...MigrationOption) (*MigrationGroup, error) {
+ cfg := newMigrationConfig(opts)
+
+ if err := m.validate(); err != nil {
+ return nil, err
+ }
+
+ if err := m.Lock(ctx); err != nil {
+ return nil, err
+ }
+ defer m.Unlock(ctx) //nolint:errcheck
+
+ migrations, err := m.MigrationsWithStatus(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ group := &MigrationGroup{
+ Migrations: migrations.Unapplied(),
+ }
+ if len(group.Migrations) == 0 {
+ return group, nil
+ }
+ group.ID = migrations.LastGroupID() + 1
+
+ for i := range group.Migrations {
+ migration := &group.Migrations[i]
+ migration.GroupID = group.ID
+
+ if !cfg.nop && migration.Up != nil {
+ if err := migration.Up(ctx, m.db); err != nil {
+ return nil, err
+ }
+ }
+
+ if err := m.MarkApplied(ctx, migration); err != nil {
+ return nil, err
+ }
+ }
+
+ return group, nil
+}
+
+func (m *Migrator) Rollback(ctx context.Context, opts ...MigrationOption) (*MigrationGroup, error) {
+ cfg := newMigrationConfig(opts)
+
+ if err := m.validate(); err != nil {
+ return nil, err
+ }
+
+ if err := m.Lock(ctx); err != nil {
+ return nil, err
+ }
+ defer m.Unlock(ctx) //nolint:errcheck
+
+ migrations, err := m.MigrationsWithStatus(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ lastGroup := migrations.LastGroup()
+
+ for i := len(lastGroup.Migrations) - 1; i >= 0; i-- {
+ migration := &lastGroup.Migrations[i]
+
+ if !cfg.nop && migration.Down != nil {
+ if err := migration.Down(ctx, m.db); err != nil {
+ return nil, err
+ }
+ }
+
+ if err := m.MarkUnapplied(ctx, migration); err != nil {
+ return nil, err
+ }
+ }
+
+ return lastGroup, nil
+}
+
+type MigrationStatus struct {
+ Migrations MigrationSlice
+ NewMigrations MigrationSlice
+ LastGroup *MigrationGroup
+}
+
+func (m *Migrator) Status(ctx context.Context) (*MigrationStatus, error) {
+ log.Printf(
+ "DEPRECATED: bun: replace Status(ctx) with " +
+ "MigrationsWithStatus(ctx)")
+
+ migrations, err := m.MigrationsWithStatus(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return &MigrationStatus{
+ Migrations: migrations,
+ NewMigrations: migrations.Unapplied(),
+ LastGroup: migrations.LastGroup(),
+ }, nil
+}
+
+func (m *Migrator) MarkCompleted(ctx context.Context) (*MigrationGroup, error) {
+ log.Printf(
+ "DEPRECATED: bun: replace MarkCompleted(ctx) with " +
+ "Migrate(ctx, migrate.WithNopMigration())")
+
+ return m.Migrate(ctx, WithNopMigration())
+}
+
+type goMigrationConfig struct {
+ packageName string
+}
+
+type GoMigrationOption func(cfg *goMigrationConfig)
+
+func WithPackageName(name string) GoMigrationOption {
+ return func(cfg *goMigrationConfig) {
+ cfg.packageName = name
+ }
+}
+
+// CreateGoMigration creates a Go migration file.
+func (m *Migrator) CreateGoMigration(
+ ctx context.Context, name string, opts ...GoMigrationOption,
+) (*MigrationFile, error) {
+ cfg := &goMigrationConfig{
+ packageName: "migrations",
+ }
+ for _, opt := range opts {
+ opt(cfg)
+ }
+
+ name, err := m.genMigrationName(name)
+ if err != nil {
+ return nil, err
+ }
+
+ fname := name + ".go"
+ fpath := filepath.Join(m.migrations.getDirectory(), fname)
+ content := fmt.Sprintf(goTemplate, cfg.packageName)
+
+ if err := ioutil.WriteFile(fpath, []byte(content), 0o644); err != nil {
+ return nil, err
+ }
+
+ mf := &MigrationFile{
+ Name: fname,
+ Path: fpath,
+ Content: content,
+ }
+ return mf, nil
+}
+
+// CreateSQLMigrations creates an up and down SQL migration files.
+func (m *Migrator) CreateSQLMigrations(ctx context.Context, name string) ([]*MigrationFile, error) {
+ name, err := m.genMigrationName(name)
+ if err != nil {
+ return nil, err
+ }
+
+ up, err := m.createSQL(ctx, name+".up.sql")
+ if err != nil {
+ return nil, err
+ }
+
+ down, err := m.createSQL(ctx, name+".down.sql")
+ if err != nil {
+ return nil, err
+ }
+
+ return []*MigrationFile{up, down}, nil
+}
+
+func (m *Migrator) createSQL(ctx context.Context, fname string) (*MigrationFile, error) {
+ fpath := filepath.Join(m.migrations.getDirectory(), fname)
+
+ if err := ioutil.WriteFile(fpath, []byte(sqlTemplate), 0o644); err != nil {
+ return nil, err
+ }
+
+ mf := &MigrationFile{
+ Name: fname,
+ Path: fpath,
+ Content: goTemplate,
+ }
+ return mf, nil
+}
+
+var nameRE = regexp.MustCompile(`^[0-9a-z_\-]+$`)
+
+func (m *Migrator) genMigrationName(name string) (string, error) {
+ const timeFormat = "20060102150405"
+
+ if name == "" {
+ return "", errors.New("migrate: migration name can't be empty")
+ }
+ if !nameRE.MatchString(name) {
+ return "", fmt.Errorf("migrate: invalid migration name: %q", name)
+ }
+
+ version := time.Now().UTC().Format(timeFormat)
+ return fmt.Sprintf("%s_%s", version, name), nil
+}
+
+// MarkApplied marks the migration as applied (applied).
+func (m *Migrator) MarkApplied(ctx context.Context, migration *Migration) error {
+ _, err := m.db.NewInsert().Model(migration).
+ ModelTableExpr(m.table).
+ Exec(ctx)
+ return err
+}
+
+// MarkUnapplied marks the migration as unapplied (new).
+func (m *Migrator) MarkUnapplied(ctx context.Context, migration *Migration) error {
+ _, err := m.db.NewDelete().
+ Model(migration).
+ ModelTableExpr(m.table).
+ Where("id = ?", migration.ID).
+ Exec(ctx)
+ return err
+}
+
+// selectAppliedMigrations selects applied (applied) migrations in descending order.
+func (m *Migrator) selectAppliedMigrations(ctx context.Context) (MigrationSlice, error) {
+ var ms MigrationSlice
+ if err := m.db.NewSelect().
+ ColumnExpr("*").
+ Model(&ms).
+ ModelTableExpr(m.table).
+ Scan(ctx); err != nil {
+ return nil, err
+ }
+ return ms, nil
+}
+
+func (m *Migrator) formattedTableName(db *bun.DB) string {
+ return db.Formatter().FormatQuery(m.table)
+}
+
+func (m *Migrator) validate() error {
+ if len(m.ms) == 0 {
+ return errors.New("migrate: there are no any migrations")
+ }
+ return nil
+}
+
+//------------------------------------------------------------------------------
+
+type migrationLock struct {
+ ID int64
+ TableName string `bun:",unique"`
+}
+
+func (m *Migrator) Lock(ctx context.Context) error {
+ lock := &migrationLock{
+ TableName: m.formattedTableName(m.db),
+ }
+ if _, err := m.db.NewInsert().
+ Model(lock).
+ ModelTableExpr(m.locksTable).
+ Exec(ctx); err != nil {
+ return fmt.Errorf("migrate: migrations table is already locked (%w)", err)
+ }
+ return nil
+}
+
+func (m *Migrator) Unlock(ctx context.Context) error {
+ tableName := m.formattedTableName(m.db)
+ _, err := m.db.NewDelete().
+ Model((*migrationLock)(nil)).
+ ModelTableExpr(m.locksTable).
+ Where("? = ?", bun.Ident("table_name"), tableName).
+ Exec(ctx)
+ return err
+}
+
+func migrationMap(ms MigrationSlice) map[string]*Migration {
+ mp := make(map[string]*Migration)
+ for i := range ms {
+ m := &ms[i]
+ mp[m.Name] = m
+ }
+ return mp
+}