github.com/wawandco/oxplugins@v0.7.11/tools/liquibase/migration.go (about)

     1  package liquibase
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"time"
     8  
     9  	"github.com/jackc/pgx/v4"
    10  )
    11  
    12  // Migration xml with liquibase format. A migration may be composed
    13  // of multiple changesets.
    14  type Migration struct {
    15  	ChangeSets []ChangeSet `xml:"changeSet"`
    16  }
    17  
    18  // ChangeSet with SQL and Rollback instructions.
    19  type ChangeSet struct {
    20  	ID          string `xml:"id,attr"`
    21  	Author      string `xml:"author,attr"`
    22  	SQL         string `xml:"sql"`
    23  	RollbackSQL string `xml:"rollback"`
    24  }
    25  
    26  // Execute a changeset takes the SQL part of the changeset and runs it.
    27  func (cs ChangeSet) Execute(conn *pgx.Conn, file string) error {
    28  	var err error
    29  	ctx := context.Background()
    30  
    31  	row := conn.QueryRow(context.Background(), `SELECT orderexecuted FROM databasechangelog ORDER BY dateexecuted desc`)
    32  	var order int
    33  	if err = row.Scan(&order); err != nil && !errors.Is(err, pgx.ErrNoRows) {
    34  		return err
    35  	}
    36  
    37  	var count int
    38  	row = conn.QueryRow(ctx, `SELECT count(*) FROM databasechangelog WHERE id = $1`, cs.ID)
    39  	if err = row.Scan(&count); err == nil && count > 0 {
    40  		return nil
    41  	}
    42  
    43  	if err != nil {
    44  		return err
    45  	}
    46  
    47  	tx, err := conn.BeginTx(ctx, pgx.TxOptions{})
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	_, err = tx.Exec(ctx, cs.SQL)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	insertStmt := `
    58  		INSERT 
    59  		INTO databasechangelog (id, author, filename, dateexecuted, orderexecuted,exectype) 
    60  		VALUES ($1, $2, $3, $4, $5, $6);
    61  	`
    62  
    63  	_, err = tx.Exec(ctx, insertStmt, cs.ID, cs.Author, file, time.Now(), order+1, "EXECUTED")
    64  	if err != nil {
    65  		return err
    66  	}
    67  
    68  	err = tx.Commit(ctx)
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	fmt.Printf("[info] Executed `%v`.\n", cs.ID)
    74  	order++
    75  
    76  	return nil
    77  }
    78  
    79  // Rollback the changeset runs the Rollback section of the
    80  // changeset.
    81  func (cs ChangeSet) Rollback(conn *pgx.Conn) error {
    82  	tx, err := conn.BeginTx(context.Background(), pgx.TxOptions{})
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	fmt.Printf("[info] Rolling back %v. \n", cs.ID)
    88  	_, err = tx.Exec(context.Background(), cs.RollbackSQL)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	_, err = tx.Exec(context.Background(), `DELETE FROM databasechangelog WHERE id = $1`, cs.ID)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	return tx.Commit(context.Background())
    99  }