Skip to content
/ satomic Public

Simple nested SQL transactions/savepoints in Golang

License

Notifications You must be signed in to change notification settings

dhui/satomic

Repository files navigation

satomic

GitHub Workflow Status (branch) Code Coverage GoDoc Go Report Card GitHub Release Supported Go versions

satomic is a Golang package that makes managing nested SQL transactions/savepoints easier

Overview

Create a Querier and use the Atomic() method. Any SQL statements inside the Atomic() method's callback function will be appropriately wrapped in a transaction or savepoint. Transaction and savepoint management will be handled for you automatically. Any error returned by the callback function (or unrecovered panic) will rollback the savepoint or transaction accordingly. A new Querier instance is also provided to the Atomic() method's callback function to allow nesting savepoints.

Status

satomic is not stable yet, so the interfaces may change in a non-backwards compatible manner. satomic follows Semantic Versioning 2.0.0. While the major version number is 0, all backwards compatible changes will be denoted by a minor version number bump. All other changes will increase the patch version number.

Example usage

package main

import (
    "context"
    "database/sql"
    "github.com/dhui/satomic"
    "github.com/dhui/satomic/savepointers/postgres"
)

// Error handling omitted for brevity. Actual code should handle errors
func main() {
    ctx := context.Background()
    var db *sql.DB  // Use an actual db

    // savepointer should match the db driver used
    q, _ := satomic.NewQuerier(ctx, db, postgres.Savepointer{}, sql.TxOptions{})

    q.Atomic(func(ctx context.Context, q satomic.Querier) error {
        // In transaction
        var dummy int
        q.QueryRowContext(ctx, "SELECT 1;").Scan(&dummy)

        q.Atomic(func(ctx context.Context, q satomic.Querier) error {
            // In first savepoint
            return q.QueryRowContext(ctx, "SELECT 2;").Scan(&dummy)
        })

        q.Atomic(func(ctx context.Context, q satomic.Querier) error {
            // In second savepoint
            q.QueryRowContext(ctx, "SELECT 3;").Scan(&dummy)

            q.Atomic(func(ctx context.Context, q satomic.Querier) error {
                // In third savepoint
                q.QueryRowContext(ctx, "SELECT 4;").Scan(&dummy)
                return nil
            })

            return nil
        })

        return nil
    })
}

A more complete example can be found in the GoDoc

For usage with sqlx, use github.com/dhui/satomic/satomicx

What's with the name?

Go SQL atomic => satomic


Inspired by sqlexp and Django's atomic decorator/context manager.