github.com/status-im/status-go@v1.1.0/protocol/sqlite/db.go (about)

     1  package sqlite
     2  
     3  import (
     4  	"database/sql"
     5  
     6  	"github.com/pkg/errors"
     7  
     8  	_ "github.com/mutecomm/go-sqlcipher/v4" // We require go sqlcipher that overrides default implementation
     9  	"github.com/status-im/migrate/v4"
    10  	"github.com/status-im/migrate/v4/database/sqlcipher"
    11  	bindata "github.com/status-im/migrate/v4/source/go_bindata"
    12  	mvdsmigrations "github.com/status-im/mvds/persistenceutil"
    13  )
    14  
    15  var migrationsTable = "status_protocol_go_" + sqlcipher.DefaultMigrationsTable
    16  
    17  // applyMigrations allows to apply bindata migrations on the current *sql.DB.
    18  // `assetNames` is a list of assets with migrations and `assetGetter` is responsible
    19  // for returning the content of the asset with a given name.
    20  func applyMigrations(db *sql.DB, assetNames []string, assetGetter func(name string) ([]byte, error)) error {
    21  	resources := bindata.Resource(
    22  		assetNames,
    23  		assetGetter,
    24  	)
    25  
    26  	source, err := bindata.WithInstance(resources)
    27  	if err != nil {
    28  		return errors.Wrap(err, "failed to create migration source")
    29  	}
    30  
    31  	driver, err := sqlcipher.WithInstance(db, &sqlcipher.Config{
    32  		MigrationsTable: migrationsTable,
    33  	})
    34  	if err != nil {
    35  		return errors.Wrap(err, "failed to create driver")
    36  	}
    37  
    38  	m, err := migrate.NewWithInstance(
    39  		"go-bindata",
    40  		source,
    41  		"sqlcipher",
    42  		driver,
    43  	)
    44  	if err != nil {
    45  		return errors.Wrap(err, "failed to create migration instance")
    46  	}
    47  
    48  	version, dirty, err := m.Version()
    49  	if err != nil && err != migrate.ErrNilVersion {
    50  		return errors.Wrap(err, "could not get version")
    51  	}
    52  
    53  	err = ApplyAdHocMigrations(version, dirty, m, db)
    54  	if err != nil {
    55  		return errors.Wrap(err, "failed to apply ad-hoc migrations")
    56  	}
    57  
    58  	if dirty {
    59  		err = ReplayLastMigration(version, m)
    60  		if err != nil {
    61  			return errors.Wrap(err, "failed to replay last migration")
    62  		}
    63  	}
    64  
    65  	if err = m.Up(); err != migrate.ErrNoChange {
    66  		return errors.Wrap(err, "failed to migrate")
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func Migrate(database *sql.DB) error {
    73  	// Apply migrations for all components.
    74  	err := mvdsmigrations.Migrate(database)
    75  	if err != nil {
    76  		return errors.Wrap(err, "failed to apply mvds migrations")
    77  	}
    78  
    79  	migrationNames, migrationGetter, err := prepareMigrations(defaultMigrations)
    80  	if err != nil {
    81  		return errors.Wrap(err, "failed to prepare status-go/protocol migrations")
    82  	}
    83  	err = applyMigrations(database, migrationNames, migrationGetter)
    84  	if err != nil {
    85  		return errors.Wrap(err, "failed to apply status-go/protocol migrations")
    86  	}
    87  	return nil
    88  }