migration

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 27, 2022 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Migrate

func Migrate[T any](db *gorm.DB, migrate func(*T), opts ...Option) *gorm.DB

Migrate can be used for migrating data from an existing database with unencrypted data to a new format which has encrypted data in the colums tagged as such. Before calling migrate, the user has to extend the database tables with columns for holding the encrypted data. Then Migrate can be called on the database with a function that works on the migrated data type and which will be executed to migrate the database entries. For more details, see the example in the godoc.

Example
//nolint:gosec // for using math/rand
package main

import (
	"fmt"
	"log"
	"math/rand"
	"time"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

func AddUsers(db *gorm.DB, count int) {
	type User struct {
		gorm.Model
		FirstName     string
		LastName      string
		VideosWatched int
		Favorites     int
	}

	users := make([]User, count)

	firstNames := []string{"Smith", "Johnson", "Williams", "Brown", "Jones", "Miller", "Davis", "Garcia", "Rodriguez", "Wilson"}
	lastNames := []string{"James", "Robert", "John", "Michael", "David", "William", "Richard", "Joseph", "Thomas", "Charles"}

	seed := time.Now().UTC().UnixNano()
	rand.Seed(seed)

	for i := range users {
		watched := rand.Intn(1000)
		favorites := rand.Intn(watched)
		users[i] = User{
			FirstName:     firstNames[rand.Intn(len(firstNames))],
			LastName:      lastNames[rand.Intn(len(lastNames))],
			VideosWatched: watched,
			Favorites:     favorites,
		}
	}

	db.Create(&users)
}

func main() {
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})
	if err != nil {
		log.Fatal(err)
	}

	{
		// The initial setup.
		// We define an initial model with encrypted data and create dummy data.
		type User struct {
			gorm.Model
			FirstName     string
			LastName      string
			VideosWatched int
			Favorites     int
		}

		_ = db.Migrator().DropTable(&User{})
		_ = db.AutoMigrate(&User{})

		AddUsers(db, 24)
	}

	{
		// The migration.
		// The model is extended with new colums for encrypted first and last names.
		type User struct {
			gorm.Model
			FirstName          string
			LastName           string
			FirstNameEncrypted string `gorm:"serializer:D1"`
			LastNameEncrypted  string `gorm:"serializer:D1"`
			VideosWatched      int
			Favorites          int
		}

		// This will adjust the database schema to have the two new columns.
		_ = db.AutoMigrate(&User{})

		// The old unencrypted first and last names, should be migrated to the encrypted columns.
		migrateUser := func(u *User) {
			u.FirstNameEncrypted = u.FirstName
			u.LastNameEncrypted = u.LastName
			// You can clear the old data at the same time if you want.
			//u.FirstName = ""
			//u.LastName = ""
		}

		// This scope is used to make sure we only migrate data that is not yet encrypted.
		unencrypted := func(db *gorm.DB) *gorm.DB {
			return db.Where(map[string]interface{}{
				"first_name_encrypted": nil,
				"last_name_encrypted":  nil},
			)
		}

		result := Migrate(db.Scopes(unencrypted), migrateUser)
		fmt.Printf("Rows affected: %d, Error: %v", result.RowsAffected, result.Error)
		// You can also specify an option to set the batch size.
		//Migrate(db, migrateUser, BatchSize(20))

		// Add some more users with unencrypted data and run again.
		AddUsers(db, 18)

		result = Migrate(db.Scopes(unencrypted), migrateUser)
		fmt.Printf("Rows affected: %d, Error: %v", result.RowsAffected, result.Error)
	}
}
Output:

Types

type Option

type Option func(*options)

Option is used to configure optional settings for the migration.

func WithBatchSize

func WithBatchSize(batchSize int) Option

WithBatchSize sets the batch size to be used when migrating data. The default batch size is 10.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL